Laravel 5.6中如何测试由首个任务触发的连续任务?
解决Laravel 5.6中测试任务触发后续任务的问题
你遇到的问题很典型——Laravel测试环境里的队列任务默认是不会自动执行的。当你用Queue::fake()模拟队列时,它只会记录哪些任务被推入队列,但不会真正运行任务的handle()方法。所以FirstJob只是被标记为“已推送”,但它内部触发SecondJob的代码根本没机会执行,自然断言第二个任务会失败。
下面是具体的解决步骤和代码示例:
核心思路
先确认第一个任务被推送,然后手动执行第一个任务的逻辑,再断言第二个任务是否被推送。
完整测试代码示例
use Illuminate\Support\Facades\Queue; use App\Jobs\FirstJob; use App\Jobs\SecondJob; public function test_first_job_triggers_second_job() { // 1. 开启队列模拟,记录所有推送的任务但不执行 Queue::fake(); // 2. 触发会推送FirstJob的业务操作(比如调用接口、服务方法等) // 示例:假设你通过POST请求触发任务推送 $this->post('/api/trigger-first-job'); // 3. 断言FirstJob已被推送,同时捕获任务实例 $capturedFirstJob = null; Queue::assertPushed(FirstJob::class, function ($job) use (&$capturedFirstJob) { $capturedFirstJob = $job; // 这里可以额外验证FirstJob的参数是否正确,比如: // return $job->user_id === 1; return true; }); // 4. 手动执行FirstJob的handle方法,触发内部的SecondJob推送逻辑 // 使用app()->call来确保依赖注入正常工作 app()->call([$capturedFirstJob, 'handle']); // 5. 现在就可以断言SecondJob是否被推送了 Queue::assertPushed(SecondJob::class, function ($job) { // 同样可以验证SecondJob的参数 // return $job->data === 'expected-data'; return true; }); }
关键注意事项
- 依赖注入处理:如果
FirstJob的handle方法依赖其他服务(比如数据库、外部API),记得在测试中模拟这些依赖,避免真实业务逻辑干扰测试结果。比如用Mockery创建模拟对象,绑定到服务容器:$mockService = Mockery::mock(YourService::class); $mockService->shouldReceive('someMethod')->andReturn('fake-result'); $this->app->instance(YourService::class, $mockService); - 避免直接访问内部属性:不要直接用
Queue::pushedJobs来获取任务,而是通过assertPushed的闭包捕获实例,这样更兼容Laravel的版本变化,也更符合测试规范。
内容的提问来源于stack exchange,提问作者Serhii H
相关产品推荐
相关产品推荐

