Laravel中如何测试控制器是否使用指定FormRequest
验证控制器是否使用指定FormRequest的测试方案
你遇到的问题核心是:用spy监听MyStoreRequest时,默认不会执行原类的validated()方法,导致返回null,控制器调用create()时参数错误;但不加状态断言又无法确认测试是否真的触发了控制器逻辑。
解决思路很直接:让spy的validated()方法返回合法的数组,这样控制器能正常走完流程,状态断言就能通过,同时还能验证FormRequest是否被调用。
完整测试代码示例
public function test_store_action_uses_my_store_request() { // 创建MyStoreRequest的间谍,并指定validated()返回合法数据 $requestSpy = $this->spy(MyStoreRequest::class); $validatedData = [ 'name' => '测试用户', 'email' => 'test@example.com', // 其他模型需要的字段... ]; $requestSpy->shouldReceive('validated')->andReturn($validatedData); // 发送请求(这里的请求参数可以随便填,因为我们已经mock了validated的返回) $response = $this->post(route('your.resource.store'), [ 'name' => '随便填的无效数据', 'email' => 'invalid-email', ]); // 现在可以正常断言响应状态了 $response->assertStatus(302); // 或者201,根据你的控制器返回逻辑调整 // 核心断言:确认FormRequest的validated方法被调用过,说明请求确实使用了该类 $requestSpy->shouldHaveReceived('validated'); }
为什么这么做能解决问题
- 默认情况下,spy如果没有指定方法的返回值,会返回
null,这就导致控制器里$request->validated()拿到null,传给Model::create()时触发参数错误。 - 手动指定
validated()的返回值后,控制器逻辑能正常执行,模型创建成功,响应状态断言自然能通过。 - 最后的
shouldHaveReceived('validated')断言是关键:它能直接证明MyStoreRequest被注入并调用了核心方法,完全满足你“验证请求是否实际使用指定FormRequest”的需求。
另一种可选方案(partial mock)
如果你不想mockvalidated()的返回,也可以用部分模拟,让原类的验证逻辑正常执行,但依然监听方法调用:
public function test_store_uses_my_store_request() { $requestMock = $this->partialMock(MyStoreRequest::class); $requestMock->shouldReceive('validated')->once(); // 这里要传符合验证规则的参数,因为partial mock会执行原类的验证逻辑 $response = $this->post(route('your.resource.store'), [ 'name' => '合法用户名', 'email' => 'valid@example.com', ]); $response->assertStatus(302); }
这种方案适合你偶尔想兼顾验证逻辑的情况,但如果你的目标只是确认FormRequest被使用,第一种方案更简洁,不需要关心验证规则。
内容的提问来源于stack exchange,提问作者IGP
相关产品推荐
相关产品推荐

