在我的控制器中,我正在使用MyModel::where(...)
,它在我的一次测试中调用数据库。我以为我可以用以下内容重载它,但它仍然在查询数据库。我该怎么做才能确保我的测试仍然需要调用::where
但是返回一个模拟模型,以便我可以继续测试这个控制器方法的其余部分?
MyModel::shouldReceive('where')
->once()
->with('param1', 'param2')
->andReturn($mockedModel);
答案 0 :(得分:3)
首先,您必须了解为什么不能模拟where
方法。那是因为类Illuminate\Database\Eloquent\Model
(Eloquent是它的别名)没有显式声明where
方法。此方法通过魔术方法__callStatic
和__call
调用,实际上是Illuminate\Database\Eloquent\Builder
(sources)的方法。
然后,您有几个选择:
您可以接受在测试中调用数据库,并在断言之前定义真实的上下文。您的测试将不那么单一,但我们可以在大多数情况下处理。
@michaelcurry解决方案很好。您可以使用查询范围或其他体系结构构建自己的抽象层(例如,在模型中自己注入查询构建器)以生成更可测试的代码。
[从未尝试]您可以直接模拟DB
外观以完全绕过数据库。您需要很好地理解Laravel核心,但这可能是编写“纯”单元测试的好方法。
无论如何,请毫不犹豫地深入了解Laravel源代码。代码很清楚,只有很少的类非常重要。这对于真正利用框架的力量至关重要。
答案 1 :(得分:1)
使用http://laravel.com/docs/eloquent#query-scopes并创建一个只返回所需数据的新函数。
如果你还没有读过“Laravel:从Apprentice到Artisan”我会建议它。将帮助您了解所有这些是如何构建的。