【问题标题】:Unable to mock Model::where() and prevent test from querying database无法模拟 Model::where() 并阻止测试查询数据库
【发布时间】:2014-02-25 15:32:00
【问题描述】:

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

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

【问题讨论】:

    标签: php laravel phpunit mockery


    【解决方案1】:

    首先,你要明白为什么不能模拟where 方法。这是因为 Illuminate\Database\Eloquent\Model 类(Eloquent 是它的别名)没有明确声明 where 方法。该方法通过__callStatic 和__call 的魔术方法调用,实际上是Illuminate\Database\Eloquent\Builder (sources) 的方法。

    那么,你有几个选择:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这个场景的好建议......但它似乎仍然在打击数据库。
      猜你喜欢
      • 1970-01-01
      • 2010-09-23
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-18
      • 1970-01-01
      相关资源
      最近更新 更多