如何在Laravel/Lumen控制器构造函数获取登录用户ID时通过API测试?
问题分析
你遇到的错误根源是:测试中调用withoutMiddleware()禁用了认证中间件,导致$request->user()返回null,控制器构造函数里访问$request->user()->userId会触发致命错误,最终接口返回的不是预期的JSON结构,seeJsonStructure断言时因找不到对应数组结构抛出assertArrayHasKey参数错误。
解决方案
方案1:模拟用户登录(推荐)
不要禁用认证中间件,而是在测试中创建并模拟登录用户,让请求携带合法的用户实例:
public function testShowOneItemReturnsOnePayroll() { // 创建测试用户(需确保User模型工厂已配置) $user = factory(App\User::class)->create(['userId' => 1001]); // 模拟用户登录 $this->actingAs($user); $this->json('GET', "intranet"); $this->seeJsonStructure([ 'data' => [ 'prId', 'userId', 'firstName', 'lastName', ... ] ]); }
这种方式贴近真实业务场景,同时保证控制器能正常获取loggedInUserId。
方案2:给控制器添加空值安全处理
如果业务允许无用户访问的场景,可以修改构造函数避免空指针错误:
private $loggedInUserId; public function __construct(Request $request) { // 使用null安全运算符,避免$request->user()为null时报错 $this->loggedInUserId = $request->user()?->userId; }
注意:需要确保控制器后续逻辑能处理loggedInUserId为null的情况。
方案3:手动给请求绑定用户(不推荐)
如果坚持要禁用中间件,可以手动为请求注入用户实例:
public function testShowOneItemReturnsOnePayroll() { $user = factory(App\User::class)->create(['userId' => 1001]); // 创建请求并设置用户解析器 $request = Request::create("intranet", 'GET'); $request->setUserResolver(fn() => $user); // 将请求绑定到容器 $this->app->instance('request', $request); $this->json('GET', "intranet"); $this->seeJsonStructure([ 'data' => [ 'prId', 'userId', 'firstName', 'lastName', ... ] ]); }
此方法操作繁琐,仅适用于特殊测试场景。
内容的提问来源于stack exchange,提问作者Wals
相关产品推荐
相关产品推荐

