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
相关产品推荐
相关产品推荐

