如何在Laravel单元测试中为Guzzle创建Mock请求?
解决Laravel中Guzzle Mock请求不生效的问题
你的问题核心是业务代码中直接硬实例化Guzzle Client,导致测试里创建的Mock Client无法被业务逻辑复用,业务类依然会创建新的真实Client去调用API。要让Mock生效,必须通过依赖注入替换掉业务类中的Client实例。
步骤1:重构业务代码,使用依赖注入
把业务类中直接new Client的逻辑改成从外部注入,或者通过Laravel容器获取Client实例。
比如你的业务类可以改成这样:
namespace App\Services; use GuzzleHttp\Client; class YourBusinessService { protected $client; // 通过构造函数注入Guzzle Client public function __construct(Client $client) { $this->client = $client; } public function makeRequest() { // 使用注入的Client发起请求,不再自己new $response = $this->client->request('GET', 'https://some-test-url.com/provider/v2/oauth2/authorize', [ 'connect_timeout' => 30 ]); // 后续业务逻辑... return $response; } }
如果不想修改构造函数,也可以通过Laravel容器动态获取:
// 在业务方法中 $client = app(Client::class); $client->request(...);
步骤2:在单元测试中绑定Mock Client到容器
测试时,创建好配置了MockHandler的Client,然后将其绑定到Laravel的服务容器中,这样业务类获取的就是Mock实例了。
完整测试代码示例:
namespace Tests\Unit; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Client; use GuzzleHttp\Psr7\Response; use App\Services\YourBusinessService; use Tests\TestCase; class YourBusinessServiceTest extends TestCase { public function test_make_request_uses_mock() { // 创建Mock响应,注意Set-Cookie要写成数组格式 $mock = new MockHandler([ new Response(200, [ 'Set-Cookie' => [ 'cookie1=cookie1_data; Domain=some-test-url.com', 'cookie2=cookie2_data; Domain=some-test-url.com', 'cookie3=cookie3_data; Domain=some-test-url.com', ] ], 'Test response'), ]); $handlerStack = HandlerStack::create($mock); $mockClient = new Client(['handler' => $handlerStack, 'cookies' => true]); // 将Mock Client绑定到容器,替换默认的Client实例 $this->app->instance(Client::class, $mockClient); // 实例化业务类(此时会自动注入Mock Client) $service = new YourBusinessService($mockClient); // 或者用容器解析:$service = app(YourBusinessService::class); // 执行测试方法 $response = $service->makeRequest(); // 断言Mock响应生效 $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals('Test response', $response->getBody()->getContents()); } }
关键注意点
- 不要在业务代码中直接
new Client,必须通过依赖注入或容器获取,这样才能在测试中替换实例。 - Mock响应的
Set-Cookie要以数组形式传递,每个cookie是独立的字符串,否则Guzzle无法正确解析多个Cookie。 - 测试时确保绑定Mock Client到容器的操作在实例化业务类之前执行。
这样修改后,单元测试就会完全使用Mock数据,不会再调用真实API,断开网络也不会出现curl错误了。
内容的提问来源于stack exchange,提问作者Nole
相关产品推荐
相关产品推荐

