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

时间:2014-11-10 10:30:06

标签: php symfony phpunit tdd mockery

我们正在试验 Mockery (0.9.2)的奇怪行为,同时使用 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')调用而设置的setUp

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

这是一个Mockery限制吗?对我们来说是一种不好的方法,可能会有一种测试气味吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

这是一个Mockery限制。当您为方法设置新的期望时,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();
  }
}
相关问题