2016-10-19 6 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関数でget(xxx)行を使用すると、両方のテストが失敗します。だから、 、私はパラメータ「FirstServiceKey」、「SecondServiceKey、のために特定のsequenzを必要としないテストケースを変更しなければならないのか...

+0

あなたは '$ this-> at(0)'の代わりに '$ this-> any()'を試しましたか? – Matteo

+0

はい、それは私の最初の試みでした。 メソッド名の期待値が0回以上呼び出されたときにに等しい 呼び出しのパラメータ0 –

+0

はい、最初は慎重に質問を読んでいません。私の答えはあなたの必要を満たすことを願って – Matteo

答えて

4

あなたはwillReturnCallbackの一例として、willReturnCallbackまたはwillReturnMap戦略を試すことができます。

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/

関連する問題