无法模拟Model :: where()并阻止测试查询数据库

时间:2014-02-02 00:18:49

标签: php laravel phpunit mockery

在我的控制器中,我正在使用MyModel::where(...),它在我的一次测试中调用数据库。我以为我可以用以下内容重载它,但它仍然在查询数据库。我该怎么做才能确保我的测试仍然需要调用::where但是返回一个模拟模型,以便我可以继续测试这个控制器方法的其余部分?

MyModel::shouldReceive('where')
  ->once()
  ->with('param1', 'param2')
  ->andReturn($mockedModel);

2 个答案:

答案 0 :(得分:3)

首先,您必须了解为什么不能模拟where方法。那是因为类Illuminate\Database\Eloquent\Model(Eloquent是它的别名)没有显式声明where方法。此方法通过魔术方法__callStatic__call调用,实际上是Illuminate\Database\Eloquent\Buildersources)的方法。

然后,您有几个选择:

  1. 您可以接受在测试中调用数据库,并在断言之前定义真实的上下文。您的测试将不那么单一,但我们可以在大多数情况下处理。

  2. @michaelcurry解决方案很好。您可以使用查询范围或其他体系结构构建自己的抽象层(例如,在模型中自己注入查询构建器)以生成更可测试的代码。

  3. [从未尝试]您可以直接模拟DB外观以完全绕过数据库。您需要很好地理解Laravel核心,但这可能是编写“纯”单元测试的好方法。

  4. 无论如何,请毫不犹豫地深入了解Laravel源代码。代码很清楚,只有很少的类非常重要。这对于真正利用框架的力量至关重要。

答案 1 :(得分:1)

使用http://laravel.com/docs/eloquent#query-scopes并创建一个只返回所需数据的新函数。

如果你还没有读过“Laravel:从Apprentice到Artisan”我会建议它。将帮助您了解所有这些是如何构建的。