php - 如何在 laravel 5 中模拟模型上的 create 方法?

标签 php unit-testing laravel eloquent mockery

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

我不想将任何资源持久保存到数据库中。

我已经创建了一个模拟对象,指定了期望,并将其绑定(bind)到应用程序实例,但是当 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
}

There was 1 error

SQLSTATE[23503]: Foreign key violation: 7 ERROR: insert or update on table "logs" violates foreign key constraint....

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

如果这无法实现,对替代策略有什么建议吗?

谢谢!

最佳答案

众所周知,静态方法在单元测试中很难处理。线路

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

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

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

有关类似问题的出色答案,请参见此处:Laravel Dependency Injection: When do you have to? When can you mock Facades? Advantages of either method?

关于php - 如何在 laravel 5 中模拟模型上的 create 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32640067/

相关文章:

c# - 如何正确实现 .net 标准库的单元测试

python - 如何使用模拟在 python 中写入和读取模拟文件对象?

validation - 显示 Laravel 4 中动态添加元素的验证错误

php - 如何在任何给定日期之前获得本周的周末?

php - 如何从闭包中终止 Eloquent 分块

java - 如何在 TestNG 中结合 Mockito 和 Spring

mysql - Laravel API 的 mysql 查询未在 performance_schema.events_statements_summary_by_digest 中被跟踪

mysql - Laravel 中删除关系时将外键设置为 'NULL'

PHP - Google Admin SDK - 使用服务帐户进行身份验证 "Not Authorized to access this resource/api"

php - 在选择选项中显示来自 mysql 的一个表?