0

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

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

2 回答 2

3

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

然后,您有几个选择:

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

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

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

无论如何,不​​要犹豫,深入了解 Laravel 源代码。代码很清晰,只有几个类非常重要。这对于真正利用框架的力量至关重要。

于 2014-02-02T19:45:19.147 回答
1

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

如果你还没有读过“Laravel:从学徒到工匠”,我会推荐它。将帮助您了解所有这些的结构。

于 2014-02-02T00:35:55.397 回答