Статические методы сами по себе не сложнее, чем методы экземпляра.Проблема возникает, когда метод - статический или другой - вызывает другие статические методы, потому что вы не можете изолировать тестируемый метод.Вот типичный пример метода, который может быть трудно проверить:
public function findUser($id) {
Assert::validIdentifier($id);
Log::debug("Looking for user $id"); // writes to a file
Database::connect(); // needs user, password, database info and a database
return Database::query(...); // needs a user table with data
}
Что вы можете проверить с помощью этого метода?
- Передача чего-либо, кроме положительных целых чисел
InvalidIdentifierException
. Database::query()
получает правильный идентификатор. - Соответствующий пользователь возвращается, когда найден,
null
, если нет.
Эти требования просты, но вы также должны настроить ведение журнала, подключиться к базе данных, загрузить ее с данными и т. д. Класс Database
должен нести единоличную ответственность за тестирование, которое он может подключать и запрашивать.Класс Log
должен сделать то же самое для регистрации.findUser()
не должен иметь дело со всем этим, но это должно произойти, потому что это зависит от них.
Если вместо этого вышеупомянутый метод сделал вызовы методов экземпляра в Database
и Log
экземплярах, тестможет передавать фиктивные объекты со скриптовыми возвращаемыми значениями, специфичными для данного теста.
function testFindUserReturnsNullWhenNotFound() {
$log = $this->getMock('Log'); // ignore all logging calls
$database = $this->getMock('Database', array('connect', 'query');
$database->expects($this->once())->method('connect');
$database->expects($this->once())->method('query')
->with('<query string>', 5)
->will($this->returnValue(null));
$dao = new UserDao($log, $database);
self::assertNull($dao->findUser(5));
}
Вышеприведенный тест не пройден, если findUser()
пренебрегает вызовом connect()
, передает неправильное значение для $id
(5
выше) или возвращает что-либо кроме null
.Прелесть в том, что база данных не задействована, что делает тест быстрым и надежным, а это означает, что он не потерпит неудачу по причинам, не связанным с тестом, таким как сбой сети или неверные образцы данных.Это позволяет вам сосредоточиться на том, что действительно имеет значение: функциональности, содержащейся в findUser()
.