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

Laravel单元测试报call to member function call() on null,如何mock FormRequest的validated?

问题原因

直接全量Mock SaveFormRequest 类时,没有初始化Laravel FormRequest 内置依赖的验证器、容器实例,ValidatesWhenResolvedTrait 中的回调调用缺少必要的对象,因此抛出call to a member function call() on null错误。

解决方案

方案1:使用Laravel原生HTTP测试(更推荐)

Laravel官方为表单请求测试提供了原生支持,无需手动Mock请求类,直接通过构造请求数据发送POST请求即可完成测试,同时可以自动触发FormRequest的验证逻辑:

public function test_add_form_logic()
{
    // 构造通过验证的合法请求数据
    $validData = [
        'name' => '测试用户',
        'phone' => '13xxxxxxxxx'
        // 补充其他业务要求的字段
    ];

    // 如果需要Mock服务层避免真实业务操作,可以提前绑定Mock
    $this->mock(YourServiceLayer::class, function ($mock) use ($validData) {
        $mock->shouldReceive('addFormDetails')
            ->once()
            ->with($validData);
    });

    // 发送POST请求到控制器对应路由
    $response = $this->post(route('form.add'), $validData);

    // 断言响应符合预期
    $response->assertRedirect(route('register'));
}

方案2:手动Partial Mock FormRequest

如果确实需要直接调用控制器方法而非走HTTP请求,可以使用局部Mock只覆盖validated方法,保留FormRequest的基础初始化逻辑:

public function test_controller_add_form()
{
    // 局部Mock,仅重写validated方法
    $saveRequest = $this->partialMock(SaveFormRequest::class, function ($mock) {
        $mock->shouldReceive('validated')
            ->once()
            ->andReturn([
                'mock_field1' => 'value1',
                'mock_field2' => 'value2'
            ]);
    });

    // 实例化控制器并传入Mock请求
    $controller = new YourController();
    $response = $controller->addForm($saveRequest);

    // 断言返回结果符合预期
    $this->assertEquals(route('register'), $response->getTargetUrl());
}
注意事项

建议单独编写SaveFormRequest的验证规则测试用例,避免在控制器测试中混合验证逻辑的校验,保证测试职责单一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:09:01