Laravel使用PHPUnit测试Artisan命令时assertPushed校验始终失败
问题根因
dispatchNow逻辑与队列模拟机制不兼容
Laravel 的dispatchNow()是同步直接执行任务的方法,完全跳过队列推送的全流程,不会向队列写入任何任务实例。哪怕你启用了Queue::fake()模拟队列环境,也捕获不到任何队列推送动作,这是断言失败的核心原因。- 测试未预置对应业务数据
测试中直接调用 Artisan 命令,但没有提前创建Model的测试记录,命令内的Model::query()->cursor()遍历不到任何数据,each闭包根本不会执行。就算把dispatchNow换成普通队列分发方法,也不会有任何 Job 被触发。
修复方案
根据你的实际业务需求选择对应改法:
方案1:符合批量迁移防内存溢出的队列执行场景
如果你本来就打算把任务推送到队列执行(每个 Job 单独进程运行,彻底避免内存溢出),需要先调整命令内的分发逻辑:
// 替换原来的同步分发写法 TestJob::dispatch($model);
再调整测试代码,先预置测试数据,再匹配对应的断言:
public function test_command_dispatch_job() { Queue::fake(); // 提前创建测试用的Model记录,保证游标能遍历到有效数据 Model::factory()->count(2)->create(); Artisan::call('random:test-job'); // 断言推送的Job数量和实际创建的Model数量一致 Queue::assertPushed(TestJob::class, 2); }
方案2:确实需要同步执行任务的场景
如果你的设计就是要同步跑任务、不走队列,那不能用 Queue::fake() 做断言,需要换成任务总线的模拟工具 Bus::fake():
public function test_command_dispatch_job() { Bus::fake(); Model::factory()->count(2)->create(); Artisan::call('random:test-job'); // 断言任务被正确分发到总线执行 Bus::assertDispatched(TestJob::class, 2); }
额外提醒:你最初提到要处理2万条记录避免内存溢出,如果用
dispatchNow同步执行,哪怕用了游标减少内存占用,Job 内的业务逻辑如果累积占用内存,还是可能触发溢出。批量迁移场景优先用队列分发的模式更稳妥。
内容的提问来源于stack exchange,提问作者Amirul Iqram
相关产品推荐
相关产品推荐

