Я знаю, что можно тестировать закрытые / защищенные методы с помощью PHPUnit, используя отражение или другие обходные пути.
Но большинство источников говорят мне, что это не Лучшая практика — писать тесты для закрытых методов внутри класса.
Предполагается, что вы тестируете класс как «черный ящик» — вы просто тестируете ожидаемое поведение, сравнивая входные данные с выходными, не учитывая внутреннюю механику. Написание тестов для классов также должно уведомлять вас о неиспользуемых частных методах, показывая отсутствие покрытия кода.
Когда я тестирую свой класс и генерирую отчет в формате HTML, он показывает, что закрытые методы не охвачены тестами, даже если строки, из которых они вызываются, абсолютно выполнены / покрыты. Я знаю, что закрытые методы выполняются, потому что, если бы они не были утверждениями, мой класс не прошел бы.
Это ожидаемое поведение в PHPUnit? Могу ли я стремиться к 100% охвату, но при этом опробовать частные методы только косвенно?
Несколько упрощенных примеров кода (с использованием RestBundle в Symfony2):
class ApiController extends FOSRestController {
/*
* @REST\View()
* @REST\Get("/api/{codes}")
*/
public function getCodesAction($codes) {
$view = new View();
$view->setHeader('Access-Control-Allow-Origin', '*');
$view->setData(array('type' => 'codes','data' => $this->_stringToArray($codes)));
$view->setFormat('json')->setHeader('Content-Type', 'application/json');
return $this->handleView($view);
}
private function _stringToArray($string){
return explode('+',$string);
}
Публичная функция отображается как «закрытая», закрытая функция косвенно покрыта, но в отчетах PHPUnit отображается красным цветом.
Тестовое задание:
class ApiControllerTest extends WebTestCase {
public function test_getCodesAction(){
$client = static::createClient();
$client->request('GET', '/api/1+2+3');
$this->assertContains('{"type": "codes", "data": [1,2,3]}', $client->getResponse()->getContent());
}
}
Конечно, это просто глупый пример, я мог бы также включить функцию explode () прямо в публичную функцию; Но контроллеры, для которых я пишу тесты, содержат гораздо более сложные и многократно используемые частные функции, которые преобразуют данные более сложными способами (но по-прежнему не имеют побочных эффектов).
В Phpunit вы можете указать Покрываемые методы со специальной аннотацией, как описано в доктор.
Вы можете сделать что-то вроде этого:
class ApiControllerTest extends WebTestCase {
/**
* @covers ApiController::getCodesAction
* @covers ApiController::_stringToArray
*/
public function test_getCodesAction(){
$client = static::createClient();
$client->request('GET', '/api/1+2+3');
$this->assertContains('{"type": "codes", "data": [1,2,3]}', $client->getResponse()->getContent());
}
}
Надеюсь это поможет
Других решений пока нет …