【问题标题】:How To Use Mockery For Mocking Nested Object Like GuzzleHttp Request如何使用 Mockery 模拟嵌套对象,如 GuzzleHttp 请求
【发布时间】:2026-01-18 07:00:02
【问题描述】:

我在 PHP 中有以下代码:

$response = $this->client->request('GET', $path, $requestBody, $headers);
$isRequestSuccess = $response->getStatusCode() === "200";

if ($isRequestSuccess) {
    return $response->getBody()->getContents();
}

似乎我成功地为请求创建了一个模拟:

$mockResponse = \Mockery::mock('GuzzleHttp\Psr7\Response');

$clientMock
    ->shouldReceive('request')
    ->once()
    ->withAnyArgs()
    ->andReturn($mockResponse);

$clientMock->shouldReceive('getStatusCode')->andReturn(200);

但是,我应该如何使用 Mockery 来模拟 getStatusCode

它应该返回GuzzleHttpPsr7\Response 对象。

我知道$clientMock返回值应该分配给一个参数,但是我应该如何模拟

$response->getStatusCode();

$response->getBody()->getContents()

如果我要模拟 getStatusCode 并返回 200,我会收到以下错误:

Method Mockery_4_GuzzleHttp_Psr7_Response::getStatusCode() does not exist on this mock object

【问题讨论】:

    标签: php unit-testing guzzle mockery psr-7


    【解决方案1】:

    这不是$request,而是$response,你最好这样命名。 $request 变量包含一个响应对象,这非常令人困惑。

    不管怎样,

    Mockery::mock(ResponseInterface::class)->shouldReceive('getStatusCode')->andReturn(200);
    

    更深入地看,您可能不必在意,该响应被模拟并且对测试无用,如果您正确设置模拟,您将进行测试,而不是测试您的代码。

    【讨论】:

    • 您的示例仅适用于getStatusCode 方法,但不一定适用于$response->getBody()->getContents()。我不是在嘲笑整个函数的响应。我想模拟它在其中调用的方法,因为它是嵌套验证整个代码的一部分。同时添加错误。
    • 我认为这是我的错。我刚刚在$mockResponse 中犯了一个错误。我没有添加makePartial 电话。
    • 对不起,你必须模拟 StreamInterface 并让它的 getContents 方法返回预期的字符串,然后配置响应模拟的 getBody 方法以返回模拟的流。