Laravel测试assertEquals报错:Target class [request]不存在,求排查
我正在编写如下Laravel测试(仅展示相关部分):
namespace Tests\Feature\Response; use App\Models\Customer; use Tests\TestCase; class ResponseTest extends TestCase { protected $customer; public function setUp(): void { parent::setUp(); $this->customer = Customer::factory()->enabled()->create(); } public function testJson(): void { $responseData = (object) ['code' => 'NOT OK']; // Test its response $this->assertEquals('OK', $responseData->code, 'response data did not respond OK'); } }
但程序未返回预期的断言失败信息“response data did not respond OK”,而是抛出错误“Target class [request] does not exist”。
工厂的相关代码如下:
public function enabled() { return $this->state(function (array $attributes) { return [ 'enabled' => 1 ]; }); }
Customer模型的相关部分:
public static function boot() { parent::boot(); $request = request(); }
奇怪的是:当不使用enabled状态时,该问题不会出现。请问我哪里操作错误?
核心原因
问题出在Customer模型的boot方法中直接调用了request()辅助函数。在Laravel测试的setUp阶段,HTTP请求实例还未被服务容器初始化,而模型的boot方法会在模型被实例化(包括工厂创建流程)时自动触发。当你使用enabled状态创建模型时,工厂的状态逻辑会触发完整的模型创建流程,进而调用boot方法里的request(),此时容器中还未绑定请求实例,因此抛出“Target class [request] does not exist”的错误。
(注:你提到不使用enabled状态时问题不出现,大概率是因为未使用状态时工厂的创建逻辑未触发模型boot方法的完整执行,但本质原因还是请求实例未初始化时调用了request())
解决方法
重构代码(推荐)
模型的职责是处理数据与核心业务逻辑,不应该直接依赖HTTP请求上下文,这违反了关注点分离原则。将依赖请求的逻辑从模型boot方法中移出,放到控制器、服务类等更适合处理HTTP请求的层级中。临时兼容方案
如果暂时无法重构,可以在模型中先判断请求实例是否存在,再执行相关逻辑:
public static function boot() { parent::boot(); // 仅当服务容器中已绑定请求实例时才执行 if (app()->has('request')) { $request = request(); // 你的业务逻辑 } }
- 测试中提前初始化请求上下文
在测试的setUp方法中,提前通过Laravel测试方法初始化请求上下文,确保请求实例被绑定到容器:
public function setUp(): void { parent::setUp(); // 提前触发请求上下文初始化 $this->get('/'); $this->customer = Customer::factory()->enabled()->create(); }
内容的提问来源于stack exchange,提问作者Peter de Groot

