【问题标题】:How can I mock the create method on a model in laravel 5?如何在 laravel 5 中模拟模型上的 create 方法?
【发布时间】:2015-12-14 21:32:30
【问题描述】:

我正在为我的 laravel 5 应用程序编写单元测试。在一个测试中,我调用了一个函数,并且需要验证它是否在被测函数中调用了另一个模型的静态 create 方法。

我不想真正将任何资源持久化到数据库中。

我创建了一个模拟对象,指定了期望,并将其绑定到应用程序实例,但是当调用 create 时,应用程序会尝试运行 SQL,而不是让模拟对象拦截函数调用。

public function testLogCreation() {
  $this->log = Mockery::mock('App\Models\Log');
  $this->log->shouldReceive('create')->once();
  $this->app->instance('App\Models\Log',$this->log);

  echo get_class($this->app['App\Models\Log']); // output: Mockery_2_App_Models_Log
}

有 1 个错误

SQLSTATE[23503]:外键违规:7 错误:在表“日志”上插入或更新违反外键约束....

我也尝试了$this->log->shouldReceive('save')->once();,因为我观察到静态create 函数调用公共save 函数,但我认为我没有在log 的正确实例上创建模拟期望。

如果这不能完成,有什么替代策略的建议吗?

谢谢!

【问题讨论】:

    标签: php unit-testing laravel eloquent mockery


    【解决方案1】:

    众所周知,静态方法在单元测试中难以应对。线

    $this->app->instance('App\Models\Log', $this->log);
    

    在应用程序中安装你的 mock 以进行依赖注入,但依赖注入只对 Laravel 创建的对象起作用。静态方法实际上一个底层对象,所以它不适用。

    您可以使用的一种方法是具有createLog 方法的工厂或服务接口。然后这个接口有一个具体的类,它使用静态方法创建日志模型(或者更好的是,不需要静态方法)。然后,您可以轻松地在测试中模拟该接口并验证是否调用了 createLog

    查看此处以获得类似问题的最佳答案:Laravel Dependency Injection: When do you have to? When can you mock Facades? Advantages of either method?

    【讨论】:

      【解决方案2】:

      您可以通过服务容器实例化一个 Eloquent 模型并在您的生产代码中对其运行 save() 来解决此问题(而不是使用 create() 方法)。

      $log = $this->app->make('App\Models\Log')->fill($array);
      $log->save();
      

      这允许您模拟实际对象而不是外观或静态方法。然后你可以像在你的例子中一样使用 Mockery,只模拟 'fill' 和 'save' 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-08
        • 2015-03-12
        • 2020-09-11
        • 2016-09-24
        • 1970-01-01
        • 1970-01-01
        • 2016-08-17
        • 2017-07-12
        相关资源
        最近更新 更多