Есть ли способ определить разные ложные ожидания для разных входных аргументов? Например, у меня есть класс уровня базы данных под названием DB. В этом классе есть метод под названием «Query (string $ query)», который принимает на входе строку запроса SQL. Могу ли я создать макет для этого класса (БД) и установить разные возвращаемые значения для разных вызовов методов запроса, которые зависят от входной строки запроса?
117
Ответы:
Библиотека Mocking PHPUnit (по умолчанию) определяет, совпадает ли ожидание, основываясь исключительно на сопоставлении, переданном
expects
параметру, и ограничению, переданному вmethod
. Из-за этого дваexpect
вызова, которые отличаются только переданными аргументамиwith
, потерпят неудачу, потому что оба будут совпадать, но только один будет подтвержден как имеющий ожидаемое поведение. См. Репродукцию после реального рабочего примера.Для вашей проблемы вам нужно использовать
->at()
или,->will($this->returnCallback(
как указано вanother question on the subject
.Пример:
Воспроизводит:
Воспроизведите, почему два вызова -> with () не работают:
Результаты в
источник
$this->anything()
качестве одного из параметров, чтобы->logicalOr()
позволить вам предоставить значение по умолчанию для других аргументов, кроме того, который вас интересует.Это не идеально для использования,
at()
если вы можете избежать этого, потому что, как утверждают их документыНачиная с версии 4.1 вы можете использовать,
withConsecutive
например.Если вы хотите, чтобы он возвращался при последовательных вызовах:
источник
Fatal error: Call to undefined method PHPUnit_Framework_MockObject_Builder_InvocationMocker::withConsecutive()
, обновился до 4.1 в мгновение ока с помощью Composer, и он работает.willReturnOnConsecutiveCalls
Убил его.Из того, что я нашел, лучший способ решить эту проблему - использовать функциональность карты значений PHPUnit.
Пример из документации PHPUnit :
Этот тест проходит. Как вы видете:
Насколько я могу судить, эта функция была введена в PHPUnit 3.6 , поэтому она достаточно «старая», чтобы ее можно было безопасно использовать практически в любых средах разработки или промежуточных средах и с любым инструментом непрерывной интеграции.
источник
Кажется, Mockery ( https://github.com/padraic/mockery ) поддерживает это. В моем случае я хочу проверить, что в базе данных создано 2 индекса:
Издевательство, работает:
PHPUnit, это не удается:
ИМХО, у Mockery более приятный синтаксис. Похоже, что это немного медленнее, чем встроенная функция имитации PHPUnits, но YMMV.
источник
вступление
Хорошо, я вижу, что есть одно решение для Mockery, поэтому, поскольку мне не нравится Mockery, я собираюсь дать вам альтернативу Prophecy, но я предлагаю вам сначала прочитать о разнице между Mockery и Prophecy.
Короче говоря : «Prophecy использует подход, называемый привязкой сообщения - это означает, что поведение метода не меняется со временем, а скорее изменяется другим методом».
Реальный проблемный код для покрытия
Решение PhpUnit Prophecy
Резюме
Еще раз, Пророчество еще круче! Моя уловка состоит в том, чтобы использовать природу связывания сообщений в Prophecy, и хотя это, к сожалению, выглядит как типичный адский код обратного вызова javascript, начинающийся с $ self = $ this; поскольку вам очень редко приходится писать подобные модульные тесты, я думаю, что это хорошее решение, и за ним, безусловно, легко следить, отлаживать, поскольку оно фактически описывает выполнение программы.
BTW: есть вторая альтернатива, но она требует изменения кода, который мы тестируем. Мы могли бы обернуть смутьянов и вынести их в отдельный класс:
можно обернуть как:
и все, но поскольку я не хотел создавать для него еще один класс, я предпочитаю первый.
источник