Intereting Posts
Как использовать функцию загрузки javascript дважды? (загрузка нагрузки) Может ли PHP-прокси-скрипт вызывать функции javascript, например щелчок? Как отправить электронную почту с локального сервера Wamp с помощью PHP? Опубликовать на другой странице в скрипте PHP Отладка PHP с точками прерывания – примеры из практики, примеры ..? php is_file всегда возвращает false Опубликовать на странице через Facebook API HTML5 и getUserMedia – запись аудио и сохранение на веб-сервер через определенное время Как очистить определенные данные от царапин с помощью простого анализатора html dom PHP Захватить последние 15 строк в txt-файле Страница таксономии типа пользовательских сообщений, все еще отображающая все сообщения Получение строк из таблицы mysql в php-массивы отключить элемент массива посредством ссылки Удаление дубликатов из массива Подтвердите номер телефона Великобритании, включая его код города

Как я могу заставить PHPUnit MockObjects возвращать разные значения на основе параметра?

У меня есть объект PHPUnit mock, который возвращает 'return value' независимо от его аргументов:

 // From inside a test... $mock = $this->getMock('myObject', 'methodToMock'); $mock->expects($this->any)) ->method('methodToMock') ->will($this->returnValue('return value')); 

То, что я хочу сделать, – это вернуть другое значение, основанное на аргументах, переданных методу mock. Я пробовал что-то вроде:

 $mock = $this->getMock('myObject', 'methodToMock'); // methodToMock('one') $mock->expects($this->any)) ->method('methodToMock') ->with($this->equalTo('one')) ->will($this->returnValue('method called with argument "one"')); // methodToMock('two') $mock->expects($this->any)) ->method('methodToMock') ->with($this->equalTo('two')) ->will($this->returnValue('method called with argument "two"')); 

Но это заставляет PHPUnit жаловаться, если mock не вызывается с аргументом 'two' , поэтому я предполагаю, что определение methodToMock('two') перезаписывает определение первого.

Поэтому мой вопрос: есть ли способ заставить PHPUnit mock object возвращать другое значение на основе его аргументов? И если да, то как?

Используйте обратный вызов. например (прямо из документации PHPUnit):

 <?php class StubTest extends PHPUnit_Framework_TestCase { public function testReturnCallbackStub() { $stub = $this->getMock( 'SomeClass', array('doSomething') ); $stub->expects($this->any()) ->method('doSomething') ->will($this->returnCallback('callback')); // $stub->doSomething() returns callback(...) } } function callback() { $args = func_get_args(); // ... } ?> 

Сделайте любую обработку, которую вы хотите в обратном вызове (), и верните результат на основе ваших $ args, если это необходимо.

Из последних документов phpUnit: «Иногда зашитый метод должен возвращать разные значения в зависимости от предопределенного списка аргументов. Вы можете использовать returnValueMap () для создания карты, которая связывает аргументы с соответствующими возвращаемыми значениями».

 $mock->expects($this->any()) ->method('getConfigValue') ->will( $this->returnValueMap( array( array('firstparam', 'secondparam', 'retval'), array('modes', 'foo', array('Array', 'of', 'modes')) ) ) ); 

У меня была аналогичная проблема (хотя и немного другая … Мне не нужно было использовать другое возвращаемое значение на основе аргументов, но пришлось проверить, чтобы 2 набора аргументов передавались одной и той же функции). Я наткнулся на что-то вроде этого:

 $mock = $this->getMock(); $mock->expects($this->at(0)) ->method('foo') ->with(...) ->will($this->returnValue(...)); $mock->expects($this->at(1)) ->method('foo') ->with(...) ->will($this->returnValue(...)); 

Это не идеально, так как это требует, чтобы порядок 2 вызовов foo () был известен, но на практике это, вероятно, не так уж плохо.

Вероятно, вы захотите сделать обратный вызов в режиме ООП:

 <?php class StubTest extends PHPUnit_Framework_TestCase { public function testReturnAction() { $object = $this->getMock('class_name', array('method_to_mock')); $object->expects($this->any()) ->method('method_to_mock') ->will($this->returnCallback(array($this, 'returnCallback')); $object->returnAction('param1'); // assert what param1 should return here $object->returnAction('param2'); // assert what param2 should return here } public function returnCallback() { $args = func_get_args(); // process $args[0] here and return the data you want to mock return 'The parameter was ' . $args[0]; } } ?> 

Это не совсем то, что вы просите, но в некоторых случаях это может помочь:

 $mock->expects( $this->any() ) ) ->method( 'methodToMock' ) ->will( $this->onConsecutiveCalls( 'one', 'two' ) ); 

onConsecutiveCalls – возвращает список значений в указанном порядке

Вы также можете вернуть аргумент следующим образом:

 $stub = $this->getMock( 'SomeClass', array('doSomething') ); $stub->expects($this->any()) ->method('doSomething') ->will($this->returnArgument(0)); 

Пропустите двухуровневый массив, где каждый элемент представляет собой массив:

  • сначала – параметры метода, а наименьшее – возвращаемое значение.

пример:

 ->willReturnMap([ ['firstArg', 'secondArg', 'returnValue'] ]) 

Вы имеете в виду что-то вроде этого?

 public function TestSomeCondition($condition){ $mockObj = $this->getMockObject(); $mockObj->setReturnValue('yourMethod',$condition); } 

У меня была аналогичная проблема, с которой я тоже не мог справиться (есть на удивление мало информации о PHPUnit). В моем случае я просто сделал каждый тестовый отдельный тестовый вход и известный выход. Я понял, что мне не нужно создавать макетный объект с разъемами для всех, мне нужен только конкретный тест для конкретного теста, и поэтому я отделил тесты и смог проверить отдельные аспекты моего кода как отдельного Блок. Я не уверен, что это может быть применимо к вам или нет, но это зависит от того, что вам нужно проверить.

 $this->BusinessMock = $this->createMock('AppBundle\Entity\Business'); public function testBusiness() { /* onConcecutiveCalls : Whether you want that the Stub returns differents values when it will be called . */ $this->BusinessMock ->method('getEmployees') ->will($this->onConsecutiveCalls( $this->returnArgument(0), $this->returnValue('employee') ) ); // first call $this->assertInstanceOf( //$this->returnArgument(0), 'argument', $this->BusinessMock->getEmployees() ); // second call $this->assertEquals('employee',$this->BusinessMock->getEmployees()) //$this->returnValue('employee'), } 

Пытаться :

 ->with($this->equalTo('one'),$this->equalTo('two))->will($this->returnValue('return value'));