2016-10-19 5 views
4

мне нужно проверить следующие функции:PHPUnit: как издеваться над несколькими вызовами метода с несколькими аргументами и без прямого порядка?

[...] 
public function createService(ServiceLocatorInterface $serviceManager) 
{ 

    $firstService = $serviceManager->get('FirstServiceKey'); 
    $secondService = $serviceManager->get('SecondServiceKey'); 

    return new SnazzyService($firstService, $secondService); 
} 
[...] 

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

class MyTest extends \PHPUnit_Framework_TestCase 
{ 
    public function testReturnValue() 
    { 
     $firstServiceMock = $this->createMock(FirstServiceInterface::class); 
     $secondServiceMock = $this->createMock(SecondServiceInterface::class); 

     $serviceManagerMock = $this->createMock(ServiceLocatorInterface::class); 

     $serviceManagerMock->expects($this->at(0)) 
      ->method('get') 
      ->with('FirstServiceKey') 
      ->will($this->returnValue($firstService)); 

     $serviceManagerMock->expects($this->at(1)) 
      ->method('get') 
      ->with('SecondServiceKey') 
      ->will($this->returnValue($secondServiceMock)); 

     $serviceFactory = new ServiceFactory($serviceManagerMock); 

     $result = $serviceFactory->createService(); 
    } 
    [...] 

или

[...] 
public function testReturnValue() 
{ 
    $firstServiceMock = $this->createMock(FirstServiceInterface::class); 
    $secondServiceMock = $this->createMock(SecondServiceInterface::class); 

    $serviceManagerMock = $this->createMock(ServiceLocatorInterface::class); 

    $serviceManagerMock->expects($this->any()) 
     ->method('get') 
     ->withConsecutive(
      ['FirstServiceKey'], 
      ['SecondServiceKey'], 
     ) 
     ->willReturnOnConsecutiveCalls(
      $this->returnValue($firstService), 
      $this->returnValue($secondServiceMock) 
     ); 

    $serviceFactory = new ServiceFactory($serviceManagerMock); 

    $result = $serviceFactory->createService(); 
} 
[...] 

Оба workes хорошо, но если я своп -> get (xxx) в функции createService, оба теста потерпят неудачу. Итак, как я должен изменить testcases, которые не нуждаются в конкретной sequenz для «FirstServiceKey» Параметры, «SecondServiceKey ...

+0

вы пытались использовать '$ this-> any()' вместо '$ this-> at (0)'? – Matteo

+0

Да, это была моя первая попытка. Приводит к ошибке: Ожидание не выполнено для имени метода равно при вызове ноль или более раз Параметр 0 для вызова –

+0

Да, изначально я не внимательно прочитал ваш вопрос. Надеюсь, мой ответ заполнит ваши необходимые – Matteo

ответ

4

Вы можете попробовать с willReturnCallback или willReturnMap стратегии, как пример willReturnCallback:

public function testReturnValue() 
{ 
    $firstServiceMock = $this->createMock(FirstServiceInterface::class); 
    $secondServiceMock = $this->createMock(SecondServiceInterface::class); 

    $serviceManagerMock = $this->createMock(ServiceLocatorInterface::class); 


    $serviceManagerMock->expects($this->any()) 
     ->method('get') 
     ->willReturnCallback(
      function ($key) use($firstServiceMock, $secondServiceMock) { 
       if ($key == 'FirstServiceKey') { 
        return $firstServiceMock; 
       } 
       if ($key == 'SecondServiceKey') { 
        return $secondServiceMock; 
       } 
       throw new \InvalidArgumentException; // or simply return; 
      } 
     ); 

    $serviceFactory = new ServiceFactory($serviceManagerMock); 

    $result = $serviceFactory->createService(); 
} 

Надеется, что это поможет

0

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

public function testReturnValue() 
{ 
    $this->container = $this->prophesize(ServiceLocatorInterface::class); 
    $firstService = $this->prophesize(FirstServiceInterface::class); 
    $secondService = $this->prophesize(SecondServiceKey::class); 

    $this->container->get('FirstServiceKey')->willReturn(firstService); 
    // And if you like 
    $this->container->get('FirstServiceKey')->shouldBeCalled(); 

    $this->container->get('SecondServiceKey')->willReturn(secondService); 
    [...] 
    $serviceFactory = new ServiceFactory(); 

    /* 
    * Little error in my example. ServiceLocatorInterface is parameter of 
    * createService() and not the constructor ;) (ZF2/3) 
    */ 

    $result = $serviceFactory->createService(
     $this->container->reveal() 
    ); 
    [...] 
} 

и теперь это не имеет значения, в какой последовательности вы создадите «$ serviceManager-> get ([...]); звонки \ o/