You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9测试命令发送通知时Notification::assertSentTo失效

问题原因及解决方法

可能的原因

  1. Notification::fake() 调用时机错误
    如果在执行Artisan::call()之后才调用Notification::fake(),fake的拦截逻辑不会对已执行的命令生效,自然捕获不到通知发送事件。

  2. 命令内的通知发送未走Laravel通知系统
    若命令里直接用Mail类发送邮件、或实例化底层发送类而非通过Notification门面/模型的notify()方法,Notification::fake()无法拦截这类绕过系统的发送行为。

  3. 测试数据不符合发送条件
    手动运行命令用的是真实环境中符合条件的数据,但测试时未创建匹配命令筛选规则的测试模型(比如即将到期的试用用户),导致命令执行时根本没有触发通知发送。

  4. 队列配置未在测试上下文生效
    即使phpunit配置了QUEUE_CONNECTION=sync,若命令里硬编码了队列连接(比如->onQueue('xxx')),或测试环境的配置未覆盖命令执行时的上下文,通知会被推送到队列而非同步执行,fake无法捕获异步队列里的通知。

正确测试方式

1. 确保Fake时机正确

先调用Notification::fake(),再执行命令,最后做断言:

public function test_trial_expire_notification_command()
{
    // 先启动通知Fake
    Notification::fake();

    // 创建符合命令筛选条件的测试用户
    $user = User::factory()->create([
        'trial_ends_at' => now()->addDays(3), // 匹配命令中"3天内到期"的规则
    ]);

    // 执行目标artisan命令
    $this->artisan('your:command-name')->assertExitCode(0);

    // 断言通知已发送给目标用户
    Notification::assertSentTo(
        $user,
        TrialNextToExpireNotification::class
    );
}

2. 检查命令内的通知发送逻辑

确保命令里使用Laravel标准的通知发送方式:

// 推荐方式:通过模型的notify方法
$user->notify(new TrialNextToExpireNotification());

// 或通过Notification门面批量发送
Notification::send($eligibleUsers, new TrialNextToExpireNotification());

避免直接调用Mail::send()等绕过通知系统的代码。

3. 验证队列配置与命令逻辑

  • 在phpunit.xml中确认队列连接配置:
    <env name="QUEUE_CONNECTION" value="sync"/>
    
  • 命令内不要硬编码队列连接,移除类似->onQueue('default')的强制队列设置。
  • 检查命令中是否有环境判断逻辑(比如if (app()->isProduction())),避免测试环境下跳过通知发送。

4. 调试命令的筛选逻辑

若断言仍失败,可在命令中临时添加调试代码,确认是否查询到目标用户:

// 在命令的handle方法中添加
$eligibleUsers = User::where('trial_ends_at', '<=', now()->addDays(3))->get();
dump($eligibleUsers->count()); // 测试时会输出查询到的用户数量

确保测试数据能被命令的筛选规则命中。

内容的提问来源于stack exchange,提问作者Juan M. Fernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:21:10