【问题标题】:Mockery forgetting byDefault setup when using shouldReceive for the same method but different arguments当使用 shouldReceive 相同的方法但不同的参数时,嘲笑忘记默认设置
【发布时间】: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()

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

提前致谢

【问题讨论】:

    标签: php symfony phpunit tdd mockery


    【解决方案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();
      }
    }
    

    【讨论】:

    • 是的,这似乎是正确的。非常感谢您的帮助! :)
    猜你喜欢
    • 2020-11-22
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    相关资源
    最近更新 更多