Я нашел дискуссию о том , тестируешь ли ты частный метод информативно.
Я решил, что в некоторых классах я хочу иметь защищенные методы, но тестировать их. Некоторые из этих методов являются статическими и короткими. Поскольку большинство открытых методов используют их, я, вероятно, смогу безопасно удалить тесты позже. Но для того, чтобы начать с подхода TDD и избежать отладки, я действительно хочу проверить их.
Я думал о следующем:
- Метод Object, как указано в ответе, кажется излишним для этого.
- Начните с общедоступных методов и, когда покрытие кода обеспечивается тестами более высокого уровня, включите их защиту и удалите тесты.
- Наследуйте класс с тестируемым интерфейсом, делая защищенные методы общедоступными
Что является лучшей практикой? Есть ли еще что-нибудь?
Кажется, что JUnit автоматически меняет защищенные методы на общедоступные, но я не смотрел на это глубже. PHP не позволяет этого через отражение .
php
unit-testing
phpunit
GrGr
источник
источник
Ответы:
Если вы используете PHP5 (> = 5.3.2) с PHPUnit, вы можете протестировать свои закрытые и защищенные методы, используя отражение, чтобы сделать их общедоступными до запуска ваших тестов:
источник
protected
метод также является частью общедоступного API, потому что любой сторонний класс может расширить его и использовать без всякой магии. Поэтому я думаю, что толькоprivate
методы попадают в категорию методов, которые не должны быть непосредственно проверены.protected
иpublic
должен быть непосредственно проверен.Вы, кажется, уже знаете, но я все равно просто повторю это; Это плохой знак, если вам нужно проверить защищенные методы. Целью модульного тестирования является тестирование интерфейса класса, а защищенные методы являются деталями реализации. Тем не менее, есть случаи, когда это имеет смысл. Если вы используете наследование, вы можете видеть, что суперкласс обеспечивает интерфейс для подкласса. Итак, здесь вам нужно будет протестировать защищенный метод (но никогда не закрытый ). Решением этой проблемы является создание подкласса для целей тестирования и использование его для предоставления методов. Например.:
Обратите внимание, что вы всегда можете заменить наследование композицией. При тестировании кода, как правило, гораздо проще иметь дело с кодом, использующим этот шаблон, поэтому вы можете рассмотреть этот вариант.
источник
Teastburn имеет правильный подход. Еще проще вызвать метод напрямую и вернуть ответ:
Вы можете назвать это просто в своих тестах:
источник
Я хотел бы предложить небольшое изменение для getMethod (), определенного в ответе Укельмана .
Эта версия изменяет getMethod (), удаляя жестко запрограммированные значения и немного упрощая использование. Я рекомендую добавить его в ваш класс PHPUnitUtil, как в примере ниже, или в ваш класс, расширяющий PHPUnit_Framework_TestCase (или, я полагаю, глобально в ваш файл PHPUnitUtil).
Так как MyClass создается в любом случае, а ReflectionClass может принимать строку или объект ...
Я также создал функцию псевдонима getProtectedMethod () для явного определения ожидаемого, но это зависит от вас.
Ура!
источник
Я думаю, что troelskn близко. Я бы сделал это вместо этого:
Затем реализуйте что-то вроде этого:
Затем вы запускаете свои тесты для TestClassToTest.
Должна быть возможность автоматически генерировать такие классы расширений путем анализа кода. Я не удивлюсь, если PHPUnit уже предлагает такой механизм (хотя я не проверял).
источник
Я собираюсь бросить свою шляпу в кольцо здесь:
Я использовал взлом __call с разной степенью успеха. Альтернативой, которую я придумал, было использование шаблона Visitor:
1: создать класс stdClass или пользовательский класс (для принудительного применения типа)
2: начните с требуемого метода и аргументов
3: убедитесь, что ваша SUT имеет метод acceptVisitor, который будет выполнять метод с аргументами, указанными в классе посещения
4: введите его в класс, который вы хотите проверить
5: SUT внедряет результат операции в посетителя
6: применить ваши условия теста к атрибуту результата посетителя
источник
Вы действительно можете использовать __call () для доступа к защищенным методам. Чтобы иметь возможность проверить этот класс
вы создаете подкласс в ExampleTest.php:
Обратите внимание, что метод __call () никоим образом не ссылается на класс, поэтому вы можете скопировать вышеприведенное для каждого класса с защищенными методами, которые вы хотите протестировать, и просто изменить объявление класса. Возможно, вы сможете поместить эту функцию в общий базовый класс, но я не пробовал.
Теперь сам контрольный пример отличается только тем, где вы создаете объект для тестирования, меняя его в ExampleExposed for Example.
Я считаю, что PHP 5.3 позволяет вам использовать отражение для непосредственного изменения доступности методов, но я предполагаю, что вам придется делать это для каждого метода в отдельности.
источник
call_user_method_array()
Начиная с PHP 4.1.0, эта функция устарела ... используйтеcall_user_func_array(array($this, $method), $args)
вместо этого. Обратите внимание, что если вы используете PHP 5.3.2+, вы можете использовать Reflection для получения доступа к защищенным / приватным методам и атрибутамAccessible
пакет, который использует отражение, чтобы позволить тестам получить доступ к закрытым / защищенным свойствам и методам классов и объектов.__call()
вызывается, только если вызывающая сторона не имеет доступа к методу. Поскольку класс и его подклассы имеют доступ к защищенным методам, вызовы к ним не будут проходить__call()
. Можете ли вы опубликовать свой код, который не работает в 5.2.7, в новом вопросе? Я использовал вышеизложенное в 5.2 и только перешел на использование отражения в 5.3.2.Я предлагаю следующий обходной путь для обходного пути / идеи "Henrik Paul" :)
Вы знаете имена частных методов вашего класса. Например, они похожи на _add (), _edit (), _delete () и т. Д.
Следовательно, когда вы хотите проверить это с точки зрения модульного тестирования, просто вызовите частные методы, добавив префикс и / или суффикс какого-нибудь общего слова (например, _addPhpunit), чтобы при вызове метода __call () (так как метод _addPhpunit () не существует) класса владельца, вы просто помещаете необходимый код в метод __call (), чтобы удалить префиксное / суффиксное слово / с (Phpunit), а затем вызвать оттуда этот выведенный приватный метод. Это еще одно хорошее использование магических методов.
Попробуйте это.
источник