当使用 shouldReceive 相同的方法但不同的参数时,嘲笑忘记默认设置

Posted

技术标签:

【中文标题】当使用 shouldReceive 相同的方法但不同的参数时,嘲笑忘记默认设置【英文标题】:Mockery forgetting byDefault setup when using shouldReceive for the same method but different arguments 【发布时间】:2015-01-06 15:06:48 【问题描述】:

我们正在试验 Mockery (0.9.2) 的一种奇怪行为,同时 tdd-ing 一个 Symfony 控制器,该控制器利用了使用 抓取的几个请求参数请求服务。我们使用 phpUnit (3.7) 作为测试框架。

我们处理 TDD 的方式是使用 setUp 方法来创建模拟并使用 byDefault() 对其进行配置,因此它们可以提供中性的快乐流程场景。然后,在每种测试方法中,我们都会具体说明我们对模拟行为的期望。

我在概念验证测试中隔离了问题,只是为了使分析更容易。我们开始吧。

这是测试类本身:

class FooTest extends \PHPUnit_Framework_TestCase

    private $request;

    public function setUp()
    
        $this->request = \Mockery::mock('Symfony\Component\HttpFoundation\Request');

        $this->request->shouldReceive('get')->with('a')->andReturnNull()->byDefault();
        $this->request->shouldReceive('get')->with('b')->andReturnNull()->byDefault();
    

    public function test_bar_checks_request_a_parameter()
    
        $this->request->shouldReceive('get')->with('a')->andReturn('a')->once();

        $foo = new Foo($this->request);
        $foo->bar();
    

这是经过测试的类:

use Symfony\Component\HttpFoundation\Request;

class Foo

    private $request;

    function __construct(Request $request)
    
        $this->request = $request;
    

    public function bar()
    
        $a = $this->request->get('a');
        $b = $this->request->get('b');
    

在测试 test_bar_checks_request_a_parameter 我希望 bar() 方法在调用 get('a') 时获得 'a'在调用 get('b') 时获取 null 时请求模拟。

但是,相反,我们得到了这个错误:

No matching handler found for Mockery_0_Symfony_Component_HttpFoundation_Request::get("b").

这似乎是说 Request 模拟忘记了我们为 get('b') 调用所做的设置

shouldReceive('get')->with('b')->andReturnNull()->byDefault()

这是嘲讽限制吗?是不是我们这边的方法不好,可能是测试气味?

提前致谢

【问题讨论】:

【参考方案1】:

这是一个嘲弄限制。当您为某个方法设置新的期望值时,Mockery 会禁用该方法的所有 byDefault() 期望值,即使它们设置了不同的参数。

有一个未解决的问题:

https://github.com/padraic/mockery/issues/353

您可以通过使用一个值数组和一个每次都会计算返回值的函数来解决这个问题。诀窍是使数组可以从测试方法中访问,以便您可以更改返回值:

class FooTest extends \PHPUnit_Framework_TestCase

  private $request;

  private $get_return_values = array();

  public function setUp()
  
      $this->request = \Mockery::mock('Symfony\Component\HttpFoundation\Request');
      $this->request->shouldReceive('get')->andReturnUsing(function($arg) 
         return isset($this->get_return_values[$arg]) ? $this->get_return_values[$arg] : null;
      );
  

  public function test_bar_checks_request_a_parameter()
  
      $this->get_return_values['a'] = 'a';

      $foo = new Foo($this->request);
      $foo->bar();
  

【讨论】:

是的,这似乎是正确的。非常感谢您的帮助! :)

以上是关于当使用 shouldReceive 相同的方法但不同的参数时,嘲笑忘记默认设置的主要内容,如果未能解决你的问题,请参考以下文章

嘲弄 shouldReceive()->once() 似乎不起作用

mockery->shouldReceive() 啥时候不应该通过?

如何在另一个被另一个调用的函数上使用 shouldReceive?

嘲弄:如何将 shouldReceive 与 method_exists 一起使用?

stringContains 参数匹配 Laravel Log 门面 shouldReceive

相同instanceof但不同类的方法不可见性