Laravel测试中如何在单次测试内切换Http fake响应数据?
解决Laravel中Http::fake()多次设置不生效的问题
问题原因
Laravel的Http::fake()会将HTTP客户端替换为FakeHttpClient实例,后续调用Http::fake()不会重新创建新的Fake实例,而是在现有实例上追加匹配规则,导致相同URL的旧规则仍优先生效。
解决方案1:用动态回调根据调用次数返回不同响应
通过闭包维护调用计数器,根据次数返回对应响应:
$callCount = 0; Http::fake([ 'https://my.apicall.com/api/v1/Invoice/Factory/saveInvoice' => function () use (&$callCount, $invoiceBody, $invoiceBody2) { $callCount++; return $callCount === 1 ? Http::response($invoiceBody, 201) : Http::response($invoiceBody2, 201); }, ]); // 执行第一次触发API调用的代码 // 执行第二次触发API调用的代码
解决方案2:重置HTTP客户端实例
在第二次调用Http::fake()前,先清除已绑定的Fake客户端实例:
// 第一次伪造响应 Http::fake([ 'https://my.apicall.com/api/v1/Invoice/Factory/saveInvoice' => Http::response($invoiceBody, 201), ]); // 执行部分代码 // 重置Fake客户端 app()->forgetInstance('http.client'); // 部分Laravel版本可直接用Http::reset(),若不存在则用上面的forgetInstance // 第二次伪造响应 Http::fake([ 'https://my.apicall.com/api/v1/Invoice/Factory/saveInvoice' => Http::response($invoiceBody2, 201), ]); // 执行更多代码
解决方案3:使用全局Fake并动态覆盖规则
先初始化全局Fake,再在每次调用前重新设置对应URL的响应规则:
// 初始化全局Fake Http::fake(); // 第一次调用前设置响应 Http::fake([ 'https://my.apicall.com/api/v1/Invoice/Factory/saveInvoice' => Http::response($invoiceBody, 201), ]); // 执行第一次代码 // 第二次调用前覆盖响应规则 Http::fake([ 'https://my.apicall.com/api/v1/Invoice/Factory/saveInvoice' => Http::response($invoiceBody2, 201), ]); // 执行第二次代码
注:此方法在部分Laravel版本中可能存在规则优先级问题,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Christian Wagner
相关产品推荐
相关产品推荐

