Покрытие кода при тестировании защищенных / частных методов с помощью PHPUnit

Я знаю, что можно протестировать частные / защищенные методы с помощью PHPUnit, используя отражение или другие обходные пути.

но большинство источников говорят мне, что это не рекомендуется писать тесты для частных методов внутри класса.

вы должны проверить класс, как если бы это был "черный ящик" - вы просто проверяете ожидаемое поведение, сравнивая входы с выходами, игнорируя внутреннюю механику. Написание тестов для классов также должно уведомлять вас к неиспользуемым частным методам, показывая отсутствие покрытия кода.

когда я тестирую свой класс и генерирую отчет HTML, он показывает частные методы, как не охваченные тестами, даже если строки, из которых они вызываются, абсолютно выполнены/покрыты. Я знаю, что частные методы выполняются, потому что, если бы они не были утверждениями на моем классе, они не прошли бы.

это ожидаемое поведение в PHPUnit? Могу ли я стремиться к охвату 100%, пока все еще испытывающ частное методы только косвенно?

некоторый упрощенный пример кода (используя RestBundle в Symfony2):

class ApiController extends FOSRestController {

/*
 * @RESTView()
 * @RESTGet("/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.

1 ответов


В помощью PHPUnit вы можете указать скрытых методах с помощью специальных аннотаций, как descrived в doc.

вы можете сделать что-то вроде этого:

    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());
        }

    }

надеюсь, что это поможет