Laravel Mock 应该至少被调用一次但被调用 0 次

Posted

技术标签:

【中文标题】Laravel Mock 应该至少被调用一次但被调用 0 次【英文标题】:Laravel Mock should be called at least once but called 0 times 【发布时间】:2020-03-28 00:23:25 【问题描述】:

我有一个工匠命令,它会触发一个名为 PasswordResetJob 的作业,该作业在调用存储库类 OrgRepository 中的方法 forcePasswordReset 时进行迭代,即方法更新用户的表。整个过程运行良好。

现在我正在尝试编写一个 Laravel 测试来模拟 OrgRepository 类并断言 forcePasswordReset 方法至少被调用一次,应该是这样,根据我提供给测试的条件。在测试中,我调用工匠命令来解雇工作; (我正在使用同步队列进行测试)这工作正常,因为作业被调用并且用户的表得到更新,因为我可以直接查看我的数据库更新。 但是,测试失败并出现错误: Mockery\Exception\InvalidCountException : Method forcePasswordReset() from Mockery_2_Repositories_OrgRepository 应该被调用 至少 1 次但调用了 0 次。

测试中的工匠调用是:

Artisan::call('shisiah:implement-org-password-reset');

我曾尝试在此模拟初始化之前和之后进行工匠调用,但我仍然遇到相同的错误。这是测试中的模拟初始化

$this->spy(OrgRepository::class, function ($mock) 
        $mock->shouldHaveReceived('forcePasswordReset');
    );

我错过了什么?我浏览了文档并在 Google 上搜索了几个小时。如果您需要任何其他信息来提供帮助,请告诉我。我正在使用 Laravel 6.0 版

编辑

我将 OrgRepository 类传递给作业类的 handle 方法,如下所示:

 public function handle(OrgRepository $repository)

    //get orgs
    $orgs = Org::where('status', true)->get();

    foreach ($orgs as $org)
       $repository->forcePasswordReset($org);
    

【问题讨论】:

仓库是通过ioc容器解析的还是你自己实例化的?您能否添加您在工作中使用 OrgRepository 的方式。 @Remul 我已经更新了问题,请检查 在测试中你在哪里初始化你的间谍? shouldHaveReceived 必须在您的作业运行后调用,而不是在此之前调用,否则您应该使用 shouldReceive @Remul 是的,在测试中,我首先调用触发工作的工匠命令,然后调用间谍 $orgs 是否包含包含某些元素的数组?分配该变量后,您可以发布dd($orgs) 的输出吗? 【参考方案1】:

问题是你在你的作业已经运行之后初始化你的间谍,这意味着在作业期间它将使用真实的类而不是间谍。

你必须在你的测试中做这样的事情:

$spy = $this->spy(OrgRepository::class);

// run your job

$spy->shouldHaveReceived('forcePasswordReset');

我们告诉 laravel 使用 spy 而不是存储库,运行作业,然后断言该方法已被调用。

Jeffrey Way 在this 截屏视频中很好地解释了这一点。

【讨论】:

以上是关于Laravel Mock 应该至少被调用一次但被调用 0 次的主要内容,如果未能解决你的问题,请参考以下文章

如何获取至少注册一次但最终状态未注册的学生列表?

如何提取在 2020 年 1 月至少访问过两次但未进行交易的所有 visitor_id 的列表(在他们 1 月的任何一次访问中)

异步 Mocha 测试(使用 Chai 断言库)应该失败,但被标记为通过

mock搭建——python——搭建一个简单的mock服务

mock搭建——python——搭建一个简单的mock服务

服务初始化一次但不是第二次