2012-06-08 4 views
38

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

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

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

$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 :: __ конструкт() должен быть числовым

Есть ли способ, чтобы сделать logicalOr насмешливый для метода с более чем один аргумент?

Заранее спасибо.

+0

Вы не сформулировали вопрос (с реальными словами). Также вы не объяснили, почему добавленный вами код специально не работает для вас. Это может показаться излишним, но эта информация поможет сделать ваш вопрос более понятным и более легким для ответа. Мы не можем смотреть в ваш мозг. – hakre

+0

@Thomas: Я пришел сюда, чтобы задать этот * точный вопрос, поэтому я обновил и поддержал ваше, надеюсь, вы не против. (И теперь мы играем в ожидающую игру ...) –

+0

@drHannibalLecter thanks – Thomas

ответ

53

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

$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-й вызов метода. Я ничего не мог сделать с любым из вариантов , которые я пробовал.

+0

Я думаю, что ключ здесь состоит в том, что 'with' принимает ряд ограничений (подразумевая' equalTo', если задано только значение). Вы * должны * иметь возможность использовать 'logicalOr', но только в контексте каждого аргумента отдельно (что может быть не очень полезно). –

+0

@JohnFlatness: Вы правы, я * должен *! :) Меня удивляет тот факт, что что-то такое основное ограничивается одним аргументом. –

+2

@drHannibalLecter Это работает, но проблема в том, что он жестко кодирует ваш тест, чтобы заботиться о внутренней реализации тестового примера. – Thomas

17

Stubbing a method call to return the value from a map

$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')); 

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

+0

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

+1

@drHannibalLecter ОК, понял. Просто confused 'with()'/'will()' – scriptin

+0

onconsecutive calls намного лучше, чем вручную (at – Blacksonic

7

В случае, если кто считает, что это не глядя на correspondent section в документации PHPUnit, вы можете использовать метод withConsecutive

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

Единственным недостатком этого в том, что код должен вызвать MyMockedMethod в порядок аргументов. Я еще не нашел пути вокруг этого.

+1

Я считаю, что это то, что функции «карты», например, willReturnMap или returnValueMap, - как поиск из параметров для возврата. – scipilot

12

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

$mock->method('myMockedMethod') 
     ->withConsecutive([$argA1, $argA2], [$argB1, $argB2], [$argC1, $argC2]) 
     ->willReturnOnConsecutiveCalls($retValue1, $retValue2, $retValue3); 
Смежные вопросы