0

0

如何在Laravel测试中伪造(Fake)HTTP请求? (Http::fake用法)

穿越時空

穿越時空

发布时间:2026-01-21 14:18:10

|

665人浏览过

|

来源于php中文网

原创

Http::fake()仅拦截Illuminate\Support\Facades\Http门面请求,不拦截GuzzleClient实例、curl_init()等;需统一用Http门面或注入可mock客户端;匹配URL须含协议域名;伪造4xx/5xx需显式调用->throw();测试后应重置fake避免污染。

如何在laravel测试中伪造(fake)http请求? (http::fake用法)

Http::fake 会拦截所有 Http::get/post 等调用,但不拦截 GuzzleClient 实例

这是最容易踩的坑:Laravel 的 Http::fake() 只作用于 Illuminate\Support\Facades\Http 门面发起的请求,对直接 new GuzzleHttp\Client() 或其他 HTTP 客户端完全无效。如果你在测试中用了自定义客户端,Http::fake() 不会起作用。

常见错误场景:

  • 服务类里写了 $client = new GuzzleHttp\Client(),然后调用 $client->get()
  • 第三方包内部硬编码了 Guzzle 实例
  • 用了 curl_init()file_get_contents()

解决办法只有两个:统一改用 Http:: 门面,或在测试中手动替换依赖(比如通过构造函数注入可 mock 的 client 接口)。

伪造不同 URL 返回不同响应,要用数组键匹配完整 URL 或正则

Http::fake() 接收一个关联数组,键是 URL 匹配规则,值是响应配置。键支持三种形式:

  • 完整 URL 字符串(如 'https://api.example.com/users'
  • 带通配符的字符串(如 'https://api.example.com/*'
  • 正则表达式(需用 PREG_PATTERN_ORDER 语法,如 '~^https://api\.example\.com/v\d+/users$~'

注意:URL 必须包含协议和域名,'/users' 这种路径写法不会匹配任何请求。

Http::fake([
    'https://api.example.com/users' => Http::response(['id' => 1, 'name' => 'Alice'], 200),
    'https://api.example.com/posts/*' => Http::response(['data' => []], 200),
    '~^https://api\.example\.com/v2/.*~' => Http::response(['error' => 'Deprecated'], 410),
]);

伪造失败响应(4xx/5xx)时,记得调用 response()->throw() 才会抛异常

默认情况下,Http::response($body, $status) 返回的响应对象不会自动抛出异常,即使状态码是 404 或 500。只有当你显式调用 ->throw(),Laravel 才会把非 2xx 响应转为 GuzzleHttp\Exception\ServerExceptionClientException

所以,如果业务代码里写了:

Viggle AI
Viggle AI

Viggle AI是一个AI驱动的3D动画生成平台,可以帮助用户创建可控角色的3D动画视频。

下载
$response = Http::get('https://api.example.com/user/999');
$data = $response->throw()->json(); // 这里才会触发异常

那么测试中伪造 404 就必须确保调用了 throw()

Http::fake([
    'https://api.example.com/user/999' => Http::response(['message' => 'Not Found'], 404),
]);

// 测试断言
$this->expectException(GuzzleHttp\Exception\ClientException::class);
Http::get('https://api.example.com/user/999')->throw();

测试结束后要清理 fake,否则会影响后续测试用例

Http::fake() 是全局状态,一旦调用就会持续生效,直到被覆盖或重置。如果你在某个 test 方法里调用了它,而没做清理,后面其他 test 方法里的 HTTP 请求也会被拦截——哪怕它们没打算 fake。

推荐做法是在 setUp() 或每个 test 开头调用 Http::fake(),并在 tearDown() 中调用 Http::preventStrayRequests() 或直接重置:

// 在 test 方法开头重置更稳妥
public function test_something()
{
    Http::fake(); // 清掉之前所有 fake 规则,只拦截不响应(即报错)
    
    Http::fake([
        'https://api.example.com/data' => Http::response(['ok' => true]),
    ]);

    // ... 测试逻辑
}

更严格的做法是加 Http::preventStrayRequests(),这样任何未被 fake 的请求都会直接失败,避免漏测真实网络调用。

真正麻烦的不是怎么 fake,而是 fake 后忘记还原,导致测试间相互污染——这个细节在 CI 环境里特别难排查。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

319

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

276

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

370

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

371

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

81

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

64

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.08.05

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

PHP面向对象基础课程(更新中)
PHP面向对象基础课程(更新中)

共12课时 | 0.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号