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

Laravel Mock should be called at least once but called 0 times

我有一个 artisan 命令触发一个名为 PasswordResetJob 的作业,它在调用一个方法 forcePasswordReset 时迭代repository class OrgRepository,该方法更新用户的 table。整个过程正常。

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

测试中的 artisan 调用是:

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

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

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

我错过了什么?我已经阅读了文档并搜索了 Google 数小时。如果您需要任何其他信息来提供帮助,请告诉我。我正在使用 Laravel 版本 6.0

编辑

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

 public function handle(OrgRepository $repository)
{
    //get orgs
    $orgs = Org::where('status', true)->get();

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

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

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

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

// run your job

$spy->shouldHaveReceived('forcePasswordReset');

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

Jeffrey Way 在 this 截屏视频中对此进行了很好的解释。