来自 Guzzle 的 PHPUnit 和模拟请求
Posted
技术标签:
【中文标题】来自 Guzzle 的 PHPUnit 和模拟请求【英文标题】:PHPUnit and mock request from Guzzle 【发布时间】:2018-08-07 08:32:59 【问题描述】:我有一个具有以下功能的课程:
public function get(string $uri) : stdClass
$this->client = new Client;
$response = $this->client->request(
'GET',
$uri,
$this->headers
);
return json_decode($response->getBody());
如何模拟来自 phpUnit 的请求方法?我尝试了不同的方法,但它总是尝试连接到指定的 uri。
我试过了:
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')
->setMethods('request')
->getMock();
$clientMock->expects($this->once())
->method('request')
->willReturn('');
但这没有用。我能做些什么?我只需要将响应模拟为空。
谢谢
PD : 客户端来自(使用 GuzzleHttp\Client)
【问题讨论】:
$this->client
是如何初始化的,你是如何通过模拟的?
你不需要返回一个实现 ResponseInterface 的对象而不是一个字符串吗?否则当你调用getBody
时它会爆炸。
当然,你的模拟应该返回一个ResponseInterface
存根,这样getBody
才能工作(你也必须模拟这个)
另外docs.guzzlephp.org/en/stable/testing.html 可能比 PHPUnit 模拟更好
我想用phpunit mocks
【参考方案1】:
我认为建议最好使用http://docs.guzzlephp.org/en/stable/testing.html#mock-handler
因为它看起来是正确执行此操作的最优雅方式。
谢谢大家
【讨论】:
Guzzle 6 的 URL(固定和基于正则表达式)模拟处理程序 - tarampampam/guzzle-url-mock 这是最好的方法吗?我看不到验证您是否向 guzzle 客户端发送正确参数的方法,只是模拟响应。【参考方案2】:模拟的响应不需要特别是任何东西,您的代码只希望它是一个具有getBody
方法的对象。因此,您可以只使用stdClass
和getBody
方法,该方法返回一些json_encoded
对象。比如:
$jsonObject = json_encode(['foo']);
$uri = 'path/to/foo/bar/';
$mockResponse = $this->getMockBuilder(\stdClass::class)->getMock();
$mockResponse->method('getBody')->willReturn($jsonObject);
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')->getMock();
$clientMock->expects($this->once())
->method('request')
->with(
'GET',
$uri,
$this->anything()
)
->willReturn($mockResponse);
$result = $yourClass->get($uri);
$expected = json_decode($jsonObject);
$this->assertSame($expected, $result);
【讨论】:
【参考方案3】:我更喜欢这种方式来模拟 PHP 中的客户端。在此示例中,我使用的是 Guzzle 客户端。
克隆代码或通过 composer 安装
$ composer require doppiogancio/mocked-client
然后……
$builder = new HandlerStackBuilder();
// Add a route with a response via callback
$builder->addRoute(
'GET', '/country/IT', static function (ServerRequestInterface $request): Response
return new Response(200, [], '"id":"+39","code":"IT","name":"Italy"');
);
// Add a route with a response in a text file
$builder->addRouteWithFile('GET', '/country/IT/json', __DIR__ . '/fixtures/country.json');
// Add a route with a response in a string
$builder->addRouteWithFile('GET', '"id":"+39","code":"IT","name":"Italy"');
// Add a route mocking directly the response
$builder->addRouteWithResponse('GET', '/admin/dashboard', new Response(401));
$client = new Client(['handler' => $builder->build()]);
一旦你模拟了客户端,你就可以像这样使用它:
$response = $client->request('GET', '/country/DE/json');
$body = (string) $response->getBody();
$country = json_decode($body, true);
print_r($country);
// will return
Array
(
[id] => +49
[code] => DE
[name] => Germany
)
【讨论】:
以上是关于来自 Guzzle 的 PHPUnit 和模拟请求的主要内容,如果未能解决你的问题,请参考以下文章
使用 PHPUnit 在 Laravel 控制器中进行单元测试 Guzzle