【发布时间】:2016-01-14 17:20:41
【问题描述】:
我不太确定在这种情况下采用哪种方式进行单元测试。单元测试 Guzzle 的示例对我来说如何在这种情况下实现都没有什么意义,或者我可能只是一起看错了。
设置:Laravel 4.2 REST API - 控制器方法在方法中使用 Guzzle 从另一个 api 请求数据,如下所示:
<?php
class Widgets extends Controller {
public function index(){
// Stuff
$client = new GuzzleHttp\Client();
$url = "api.example.com";
$response = $client->request('POST', $url, ['body' => array(...)]);
// More stuff
}
}
?>
我认为我可以按如下方式进行单元测试,一切都会正常工作。
function testGetAllWidgets(){
$mock_response = array('foo' => 'bar');
$mock = new MockHandler([
new Response(200, $mock_response),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
$response = $this->call('GET', '/widgets');
// Do asserts, etc.
}
但是,Guzzle 仍在向外部服务发出实际的 HTTP 请求。我的猜测可能是以某种方式在 Controller 方法中设置客户端创建以使用 $handler,但我无法想象这是正确的方法。我错过了什么?
编辑 我的解决方案如下:
这个解决方案感觉是最正确的,也是 Laravel 的方式。 (See IoC Containers)
我会在每个 api 调用上方添加这个(根据 api 调用中需要模拟多少外部调用来更改模拟响应)。
$this->app->bind('MyController', function($app){
$response_200 = json_encode(array("status" => "successful"));
$response_300 = json_encode("MULTIPLE_CHOICES");
$mock = new MockHandler([
new Response(200, [], $response_200),
new Response(300, [], $response_300)
]);
$handler = HandlerStack::create($mock);
return new MyController(new Client(['handler' => $handler]));
});
$params = array();
$response = $this->call('PUT', '/my-route', $params);
如果控制器需要 Guzzle 客户端,我将其添加到控制器中:
public function __construct(GuzzleHttp\Client $client)
{
$this->client = $client;
}
然后将 $this->client 用于所有 api 调用。
【问题讨论】:
标签: php unit-testing laravel phpunit guzzle