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

Laravel视图测试报错:Attempt to read property 'unreadNotifications' on null

解决Laravel直接渲染Blade视图测试时unreadNotifications为空的问题

问题背景

我需要给拥有特定角色的用户在layouts.sidebar.blade.php中添加专属链接,测试时遇到了异常:

  • 场景:AppServiceProvider为所有视图注册了NotificationComposer,代码如下:
    $view->with('unreadNotificationCount', count(request()->user()->unreadNotifications));
    
  • 直接渲染sidebar视图的测试用例会抛出Attempt to read property "unreadNotifications" on null异常:
    /** @test */
    public function user_with_role_can_see_link_in_the_sidebar()
    {
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->userRole)->blade('layouts.sidebar');
        $response->assertSee($link);
    }
    
    /** @test */
    public function normal_user_cannot_see_link_in_the_sidebar()
    {
        $link = route('my-web.new-page');
        $response = $this->actingAs($this->user)->blade('layouts.sidebar');
        $response->assertDontSee($link);
    }
    
  • 当前只能通过请求首页间接测试,但希望直接测试sidebar视图,不依赖首页路由。

原因分析

问题出在request()->user()的使用上:actingAs()确实设置了认证用户,但直接调用->blade()渲染视图时,request()实例的用户解析器并未正确关联到当前认证用户,导致request()->user()返回null,进而触发调用unreadNotifications的异常。

解决方案

方案1:改用auth()->user()替代request()->user()

修改NotificationComposer的代码,用auth() facade直接获取认证用户,同时用optional()处理未登录场景,让代码更健壮:

$view->with('unreadNotificationCount', optional(auth()->user())->unreadNotifications->count() ?? 0);

不管是HTTP请求还是直接渲染视图,只要通过actingAs()设置了认证用户,auth()->user()都能正确获取到用户实例,避免null报错。

方案2:在测试中手动绑定请求的用户

如果不想修改Composer代码,可以在测试里手动为request()设置用户解析器:

/** @test */
public function user_with_role_can_see_link_in_the_sidebar()
{
    $link = route('my-web.new-page');
    
    // 手动将请求的用户指向当前认证用户
    request()->setUserResolver(fn () => $this->userRole);
    
    $response = $this->blade('layouts.sidebar');
    $response->assertSee($link);
}

/** @test */
public function normal_user_cannot_see_link_in_the_sidebar()
{
    $link = route('my-web.new-page');
    
    request()->setUserResolver(fn () => $this->user);
    
    $response = $this->blade('layouts.sidebar');
    $response->assertDontSee($link);
}

这样request()->user()就能正确获取到actingAs()设置的用户,测试可以正常执行。

内容的提问来源于stack exchange,提问作者bozsudo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:07:20