PHPUnit: как мне высмеять несколько вызовов методов с несколькими аргументами?

Я пишу unit test для метода с использованием PHPUnit. Метод, который я тестирую, вызывает вызов одного и того же метода на одном и том же объекте 3 раза, но с разными наборами аргументов. Мой вопрос похож на вопросы, заданные здесь и здесь

Вопросы, заданные в других сообщениях, связаны с издевательскими методами, которые принимают только один аргумент.

Однако мой метод принимает несколько аргументов, и мне нужно что-то вроде этого:

$mock->expects($this->exactly(3))
     ->method('MyMockedMethod')
     ->with($this->logicalOr($this->equalTo($arg1, $arg2, arg3....argNb),
                             $this->equalTo($arg1b, $arg2b, arg3b....argNb),
                             $this->equalTo($arg1c, $arg2c, arg3c....argNc)
         ))

Этот код не работает, потому что equalTo() проверяет только один аргумент. Предоставление ему более одного аргумента вызывает исключение:

Аргумент № 2 PHPUnit_Framework_Constraint_IsEqual:: __ construct() должен быть числовым

Есть ли способ сделать logicalOr mocking для метода с более чем одним аргументом?

Спасибо заранее.

Ответ 1

В моем случае ответ оказался довольно простым:

$this->expects($this->at(0))
    ->method('write')
    ->with(/* first set of params */);

$this->expects($this->at(1))
    ->method('write')
    ->with(/* second set of params */);

Ключ должен использовать $this->at(n), при этом n является N-м вызовом метода. Я не мог ничего сделать с любыми вариантами logicalOr(), которые я пробовал.

Ответ 2

Остановка вызова метода для возврата значения из карты

$map = array(
    array('arg1_1', 'arg2_1', 'arg3_1', 'return_1'),
    array('arg1_2', 'arg2_2', 'arg3_2', 'return_2'),
    array('arg1_3', 'arg2_3', 'arg3_3', 'return_3'),
);
$mock->expects($this->exactly(3))
    ->method('MyMockedMethod')
    ->will($this->returnValueMap($map));

Или вы можете использовать

$mock->expects($this->exactly(3))
    ->method('MyMockedMethod')
    ->will($this->onConsecutiveCalls('return_1', 'return_2', 'return_3'));

если вам не нужно указывать входные аргументы

Ответ 3

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

    $mock->method('myMockedMethod')
         ->withConsecutive([$argA1, $argA2], [$argB1, $argB2], [$argC1, $argC2])
         ->willReturnOnConsecutiveCalls($retValue1, $retValue2, $retValue3);

Ответ 4

Если кто-то находит это, не глядя на соответствующий раздел в документации phpunit, вы можете использовать withConsecutive метод

$mock->expects($this->exactly(3))
     ->method('MyMockedMethod')
     ->withConsecutive(
         [$arg1, $arg2, $arg3....$argNb],
         [arg1b, $arg2b, $arg3b....$argNb],
         [$arg1c, $arg2c, $arg3c....$argNc]
         ...
     );

Единственным недостатком этого является то, что код ДОЛЖЕН вызывать MyMockedMethod в порядке поставленных аргументов. Я еще не нашел способ обойти это.