Intereting Posts

Рекомендации по проверке защищенных методов с помощью PHPUnit (на абстрактных классах)

С PHPUnit и PHP> = 5.3 можно проверить защищенные методы. На следующей странице в stackoverflow описывается наилучшая практика:

«Рекомендации по проверке защищенных методов с помощью PHPUnit»

protected static function callProtectedMethod($name, $classname, $params) { $class = new ReflectionClass($classname); $method = $class->getMethod($name); $method->setAccessible(true); $obj = new $classname($params); return $method->invokeArgs($obj, $params); } 

Для тестирования открытых методов в абстрактных классах легко использовать PHPUnit. Протестировать защищенные методы на обычных классах легко с помощью вышеприведенного подхода. Чтобы проверить защищенные методы на абстрактных классах, нужно как-то …

Я знаю, что PHPUnit выводит абстрактные классы и «реализует» абстрактные методы в конкретном классе и запускает тесты против этого конкретного класса, но я не знаю, как интегрировать это в описанный выше подход, чтобы иметь callProtectedMethodOnAbstractClasses ().

Как вы проводите такие тесты?

PS: Вопрос НЕ об истине тестирования защищенных методов (см .: white-, gray- and blackbox-testing). Необходимость тестирования защищенных методов зависит от вашей стратегии тестирования.

    Поскольку вы просите «передовой опыт», я отвечу на другой подход:

    Не проверяйте защищенные и частные методы

    Просто потому, что вы можете это не значит, что вам нужно.

    Вы хотите проверить, работает ли класс. Это означает, что все функции, которые вы можете вызвать на него (все общедоступные), возвращают правильные значения (и, возможно, вызывают правильные функции на переданных объектах) и ничего больше .

    Вам все равно, как это реализовано в классе.

    Имхо, это даже мешает вам написать тест на что-либо непубличное по двум причинам:

    • Время

    Написание тестов занимает больше времени, так как вам нужно больше, и рефакторинг также занимает больше времени. Если вы перемещаете код в классе без изменения его поведения, вам не потребуется обновлять его тесты. Тесты должны сказать вам, что все еще работает!

    • Значительное покрытие кода

    Если вы пишете тест для каждого защищенного метода, вы теряете одно наследуемое преимущество от отчета о покрытии кода: он не скажет вам, какие защищенные функции больше не вызывают . То есть (imho) плохо, потому что вы либо не проверяете все общедоступные методы правильно (почему существует метод, который не вызывается, если вы проверяете каждый случай?), Или вам действительно не нужен этот метод, но поскольку это «зеленый», вы не задумываетесь.

    Чтобы процитировать автора PHPUnit

    Итак: просто потому, что тестирование защищенных и частных атрибутов и методов возможно, не означает, что это «хорошая вещь».

    http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html

    Поскольку реальный мир иногда отличается

    ...->setAccessible() отлично подходит для обычных методов

    для абстрактного использования материалов ...->getMockForAbstractClass()

    Но, пожалуйста, сделайте это, только если это действительно необходимо.

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

    Предположение: вы хотите называть конкретные защищенные методы абстрактным классом.

    Создайте макет объекта для абстрактного класса и передайте его в эту модифицированную форму callProtectedMethod() .

     public static function callProtectedMethod($object, $method, array $args=array()) { $class = new ReflectionClass(get_class($object)); $method = $class->getMethod($method); $method->setAccessible(true); return $method->invokeArgs($object, $args); } public function testGetArea() { $rect = $this->getMockForAbstractClass('RandomRectangle'); self::callProtectedMethod($rect, 'setWidth', array(7)); self::callProtectedMethod($rect, 'setHeight', array(3)); self::assertEquals(21, $rect->getArea()); } 

    Вы можете инкапсулировать это в один метод, но я предпочитаю передавать объект, чтобы тест мог вызывать несколько защищенных / приватных методов на одном и том же объекте. Чтобы сделать это, используйте $class->isAbstract() чтобы решить, как построить объект.