【问题标题】:PHPUnit Mock Change the expectations laterPHPUnit Mock 以后改期望
【发布时间】:2018-09-05 19:36:47
【问题描述】:

我有一个简单的用例。我想要一个 setUp 方法,它会导致我的模拟对象返回默认值:

$this->myservice
        ->expects($this->any())
        ->method('checkUniqueness')
        ->will($this->returnValue(true));

但是在一些测试中,我想返回一个不同的值:

$this->myservice
        ->expects($this->exactly(1))
        ->method('checkUniqueness')
        ->will($this->returnValue(false));

我过去曾在 C++ 中使用过 GoogleMock,它有“returnByDefault”或其他东西来处理它。我不知道这在 PHPUnit 中是否可行(没有 api 文档,代码很难通读以找到我想要的)。

现在我不能只将$this->myservice 更改为新的模拟,因为在设置中,我将它传递给其他需要模拟或测试的东西。

我唯一的其他解决方案是我失去了设置的好处,而不得不为每次测试构建所有模拟。

【问题讨论】:

    标签: php mocking phpunit


    【解决方案1】:

    您可以将setUp() 代码移动到另一个具有参数的方法中。然后从setUp() 调用此方法,您也可以从您的测试方法中调用它,但参数与默认参数不同。

    【讨论】:

    • 如何解决这个问题?无论如何都会调用setUp() 方法
    • @MassimilianoArione 是的,但您可以重新创建您的 $this->myservice 并更改返回值
    【解决方案2】:

    继续在setUp() 中构建模拟,但在每个测试中分别设置期望:

    class FooTest extends PHPUnit_Framework_TestCase {
      private $myservice;
      private $foo;
      public function setUp(){
        $this->myService = $this->getMockBuilder('myservice')->getMock();
        $this->foo = new Foo($this->myService);
      }
    
    
      public function testUniqueThing(){
         $this->myservice
            ->expects($this->any())
            ->method('checkUniqueness')
            ->will($this->returnValue(true));
    
         $this->assertEqual('baz', $this->foo->calculateTheThing());
      }
    
      public function testNonUniqueThing(){
         $this->myservice
            ->expects($this->any())
            ->method('checkUniqueness')
            ->will($this->returnValue(false));
    
         $this->assertEqual('bar', $this->foo->calculateTheThing());
    
      }
    
    
    }
    

    这两个期望不会相互干扰,因为 PHPUnit 会实例化一个新的 FooTest 实例来运行每个测试。

    【讨论】:

      【解决方案3】:

      另一个小技巧是通过引用传递变量。这样你就可以操纵价值:

      public function callApi(string $endpoint):bool
      {
          // some logic ...
      }
      
      public function getCurlInfo():array 
      {
          // returns curl info about the last request
      }
      

      上面的代码有 2 个公共方法:callApi() 调用 API,第二个 getCurlInfo()-method 提供有关已完成的最后一个请求的信息。我们可以通过传递一个变量作为参考,根据为callApi() 提供/模拟的参数模拟getCurlInfo() 的输出:

      $mockedHttpCode = 0;
      $this->mockedApi
          ->method('callApi')
          ->will(
              // pass variable by reference:
              $this->returnCallback(function () use (&$mockedHttpCode) {
                  $args = func_get_args();
                  $maps = [
                      ['endpoint/x', true, 200],
                      ['endpoint/y', false, 404],
                      ['endpoint/z', false, 403],
                  ];
                  foreach ($maps as $map) {
                      if ($args == array_slice($map, 0, count($args))) {
                          // change variable:
                          $mockedHttpCode = $map[count($args) + 1];
                          return $map[count($args)];
                      }
                  }
                  return [];
              })
          );
      
      $this->mockedApi
          ->method('getCurlInfo')
          // pass variable by reference:
          ->willReturn(['http_code' => &$mockedHttpCode]);
      

      如果您仔细观察,returnCallback()-logic 实际上与returnValueMap() 做的事情相同,只是在我们的例子中我们可以添加第三个参数:来自服务器的预期响应代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-17
        • 2020-09-01
        • 2015-04-04
        • 2019-09-06
        • 2010-12-10
        • 2011-11-23
        • 2011-11-17
        相关资源
        最近更新 更多