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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 07:17:32