如何使用 Mockery 模拟嵌套对象,如 GuzzleHttp 请求

Posted

技术标签:

【中文标题】如何使用 Mockery 模拟嵌套对象,如 GuzzleHttp 请求【英文标题】:How To Use Mockery For Mocking Nested Object Like GuzzleHttp Request 【发布时间】:2020-10-05 15:38:12 【问题描述】:

我在 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

【问题讨论】:

【参考方案1】:

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

不管怎样,

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

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

【讨论】:

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

以上是关于如何使用 Mockery 模拟嵌套对象,如 GuzzleHttp 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 mockery 来模拟 httpclient

这个模拟对象上不存在方法 - Laravel,Mockery

10.9 guz模拟题题解

如何使用 mockery 来模拟没有命名空间的全局类?

如何使用 Mockery 在模拟方法的第 N 次调用中引发异常

将 Laravel Input 属性注入 Mockery 会话对象