2017-08-03 79 views
0

我的情況是類似如下:PHPUnit的模擬返回值,並呼籲針對不同方法的具體參數同等級的次數

class ToMock 
{ 
    public function iReturn() 
    { 
     return time(); 
    } 

    public function callMe1($arg1, $arg2) 
    { 
     return true; 
    } 

    public function callMe2($arg1, $arg2) 
    { 
     return true; 
    } 
} 

class ToTest 
{ 
    public function feedMe(ToMock $toMock) 
    { 
     if ($toMock->iReturn() > 100) { 
      $toMock->callMe1(5, 10); 
     } 

     if ($toMock->iReturn() < 200) { 
      $toMock->callMe2(15, 20); 
     } 
    } 
} 

現在,我要測試是否ToMock::iReturn()返回150,ToTest::feedMe()電話ToMock::callMe1()一旦與5和10,並ToMock::callMe2()一次用15和20

我知道可以嘲笑ToMock::iReturn返回150,我還可以模擬ToMock期待與提供的參數的特定方法一次。但是,是否有可能在同一時間將所有這些一起完成?如果是的話,它會是什麼樣子?

回答

1

是的,它是。

這裏的覆蓋ToTest測試的例子:

<?php 

use PHPUnit\Framework\TestCase; 

class ToTestTest extends TestCase 
{ 
    /** 
    * @dataProvider providerTimeBetween0And100 
    * 
    * @param int $time 
    */ 
    public function testFeedMeWhenTimeIsBetween0And100($time) 
    { 
     $toMock = $this->createMock(ToMock::class); 

     $toMock 
      ->expects($this->exactly(2)) 
      ->method('iReturn') 
      ->willReturn($time); 

     $toMock 
      ->expects($this->never()) 
      ->method('callMe1'); 

     $toMock 
      ->expects($this->once()) 
      ->method('callMe2') 
      ->with(
       $this->identicalTo(15), 
       $this->identicalTo(20) 
      ); 

     $toTest = new ToTest(); 

     $toTest->feedMe($toMock); 
    } 

    public function providerTimeBetween0And100() 
    { 
     return $this->providerTimeBetween(0, 100); 
    } 

    /** 
    * @dataProvider providerTimeBetween101And199 
    * 
    * @param int $time 
    */ 
    public function testFeedMeWhenTimeIsBetween101And199($time) 
    { 
     $toMock = $this->createMock(ToMock::class); 

     $toMock 
      ->expects($this->exactly(2)) 
      ->method('iReturn') 
      ->willReturn($time); 

     $toMock 
      ->expects($this->once()) 
      ->method('callMe1') 
      ->with(
       $this->identicalTo(5), 
       $this->identicalTo(10) 
      ); 

     $toMock 
      ->expects($this->once()) 
      ->method('callMe2') 
      ->with(
       $this->identicalTo(15), 
       $this->identicalTo(20) 
      ); 

     $toTest = new ToTest(); 

     $toTest->feedMe($toMock); 
    } 

    public function providerTimeBetween101And199() 
    { 
     return $this->providerTimeBetween(101, 199); 
    } 
    /** 
    * @dataProvider providerTimeGreaterThan199 
    * 
    * @param int $time 
    */ 
    public function testFeedMeWhenTimeIsGreaterThan199($time) 
    { 
     $toMock = $this->createMock(ToMock::class); 

     $toMock 
      ->expects($this->exactly(2)) 
      ->method('iReturn') 
      ->willReturn($time); 

     $toMock 
      ->expects($this->once()) 
      ->method('callMe1') 
      ->with(
       $this->identicalTo(5), 
       $this->identicalTo(10) 
      ); 

     $toMock 
      ->expects($this->never()) 
      ->method('callMe2'); 

     $toTest = new ToTest(); 

     $toTest->feedMe($toMock); 
    } 

    public function providerTimeGreaterThan199() 
    { 
     return $this->providerTimeBetween(200, 300); 
    } 

    private function providerTimeBetween($min, $max) 
    { 
     for ($time = $min; $time < $max; ++$time) { 
      yield [ 
       $time 
      ]; 
     } 
    } 
} 

注多的期望是如何設置使用expects(),並進一步限制。所有這些都可以輕鬆組合。

爲了參考,見:

1

如果我理解正確你的問題,然後測試代碼可能看起來像

class MockingExpectationsTest extends PHPUnit_Framework_TestCase 
{ 
    private $obj; 
    private $mock; 

    public function setUp(){ 
     $this->mock = $this->createMock(ToMock::class); 
     $this->obj = new ToTest(); 
    } 

    public function testExpectations(){ 
     $this->mock->expects($this->exactly(2)) 
        ->method('iReturn') 
        ->willReturn(150); 
     $this->mock->expects($this->exactly(1)) 
        ->method('callMe1') 
        ->with(5, 10); 
     $this->mock->expects($this->exactly(1)) 
        ->method('callMe2') 
        ->with(15, 20); 
     $this->obj->feedMe($this->mock); 
    } 
} 
相關問題