2016-10-19 55 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罰款,但如果我換了 - >在createService函數中獲取(xxx)行,這兩個測試都會失敗。 那麼,如何做我必須要改變它不需要對參數的FirstServiceKey「特定sequenz的測試用例,「SecondServiceKey,...

+0

你嘗試過使用'$ this-> any()'而不是'$ this-> at(0)'? – Matteo

+0

是的,那是我第一次嘗試。導致錯誤: 調用方法名稱的期望失敗等於調用零次或更多次 參數0用於調用 –

+0

是的,最初我沒有仔細閱讀您的問題。我希望我的回答能夠滿足你的需求 – Matteo

回答

4

你可以用willReturnCallbackwillReturnMap戰略嘗試,作爲實例,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([...]);''電話\\/

相關問題