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

如何使用GuzzleHttp MockHandler延迟5秒返回Mock响应?

问题描述

我有以下PHP/PHPUnit代码:

<?php

namespace Experiments\Tests;

use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\RequestOptions;
use PHPUnit\Framework\TestCase;

final class ApiGatewayTest extends TestCase
{

    public function testExecute()
    {

        $req = json_decode('{ "root": { "param1": [ "value1" ] } }', true);
        $resp = '{ "echo": { "root": { "param1": [ "value1" ] } } }';

        $options = [
            RequestOptions::HEADERS => [
                'Content-Type' => 'application/json',
            ],
            RequestOptions::JSON =>  $req,
            RequestOptions::TIMEOUT => 10,
        ];

        $handlerStack = HandlerStack::create(
            new MockHandler([new Response(200, ['Content-Type' => 'application/json'], $resp)])
        );

        $client = new HttpClient(['handler' => $handlerStack]);

        $response = $client->request(
            'POST',
            'whatever-just-mocking',
            $options
        );

        $responseBodyJson = (string) $response->getBody();
        $responseBody = json_decode($responseBodyJson, true);

        $this->assertSame('value1', $responseBody['echo']['root']['param1'][0]);
    }
}

上述单元测试运行正常,可通过以下命令测试:

$ ./vendor/bin/phpunit --filter 'testExecute\b'

我需要让Mock响应延迟5秒返回,以便在上述测试类中实现并测试超时处理逻辑,请问该如何实现?

实现方法

要给Guzzle的Mock响应添加延迟,你可以利用MockHandler结合匿名函数模拟延迟逻辑,同时调整超时时间触发超时异常,具体步骤如下:

  1. 在MockHandler的响应列表中,用匿名函数替代直接返回Response对象,在函数内部加入sleep(5)模拟服务端延迟
  2. 将请求的超时时间设置为小于延迟的数值(比如3秒),触发Guzzle的超时异常
  3. 通过PHPUnit的断言方法验证超时异常是否抛出,完成超时逻辑测试

修改后的测试代码示例:

<?php

namespace Experiments\Tests;

use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\RequestOptions;
use PHPUnit\Framework\TestCase;

final class ApiGatewayTest extends TestCase
{

    public function testExecuteTimeout()
    {
        $req = json_decode('{ "root": { "param1": [ "value1" ] } }', true);
        $resp = '{ "echo": { "root": { "param1": [ "value1" ] } } }';

        // 设置超时时间为3秒,短于模拟的5秒延迟,确保触发超时
        $options = [
            RequestOptions::HEADERS => [
                'Content-Type' => 'application/json',
            ],
            RequestOptions::JSON =>  $req,
            RequestOptions::TIMEOUT => 3,
        ];

        $mockHandler = new MockHandler([
            // 用匿名函数模拟带延迟的响应
            function (Request $request) use ($resp) {
                sleep(5); // 模拟5秒延迟
                return new Response(200, ['Content-Type' => 'application/json'], $resp);
            }
        ]);

        $handlerStack = HandlerStack::create($mockHandler);
        $client = new HttpClient(['handler' => $handlerStack]);

        // 断言会抛出超时相关的异常
        $this->expectException(ConnectException::class);
        $this->expectExceptionMessageMatches('/timeout/');

        $client->request(
            'POST',
            'whatever-just-mocking',
            $options
        );
    }
}

关键细节

  • 匿名函数接收Request对象作为参数,执行休眠逻辑后返回Response,完美模拟真实请求的延迟场景
  • 超时时间需小于模拟的延迟时长,否则无法触发超时异常
  • 使用expectException和expectExceptionMessageMatches精准断言超时异常的类型和内容,确保超时逻辑符合预期

运行测试的命令:

$ ./vendor/bin/phpunit --filter 'testExecuteTimeout\b'

内容的提问来源于stack exchange,提问作者Viewsonic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:40:43