smb*_*smb 5 php phpunit unit-testing laravel guzzle
我不太确定在这种情况下采用单元测试的方法.没有单元测试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
}
}
?>
Run Code Online (Sandbox Code Playgroud)
我以为我可以按照以下方式进行单元测试,一切都会正常工作.
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.
}
Run Code Online (Sandbox Code Playgroud)
但是,Guzzle仍在向外部服务发出实际的HTTP请求.我的猜测可能是在Controller方法中设置客户端创建以使用$ handler,但我无法想象这是正确的方法.我错过了什么?
编辑 我的解决方案最终如下:
这个解决方案感觉最正确,而且是Laravel方式.(参见IoC容器)
我会在每个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);
Run Code Online (Sandbox Code Playgroud)
如果控制器需要Guzzle客户端,我将其添加到控制器:
public function __construct(GuzzleHttp\Client $client)
{
$this->client = $client;
}
Run Code Online (Sandbox Code Playgroud)
然后将使用$ this-> client进行所有api调用.
对此的"经典TDD"回应是你不应该对Guzzle进行单元测试.Guzzle是一个第三方库,应该由自己的开发人员完全测试(并且).
您需要测试的是您的代码是否正确调用Guzzle,而不是Guzzle是否在代码调用时工作.
这样做的方法如下:
而不是做一个new Guzzle()
在你的控制器,则应该通过一个狂饮对象为使用依赖注入控制器.幸运的是,Laravel让这很容易; 你需要做的就是为你的控制器类提供一个构造函数方法,并将一个Guzzle对象定义为它的一个参数.Laravel将完成剩余的创建对象并将其传递给您.然后,构造函数可以将其复制到类属性,以便其他方法可以使用它.
你的班级现在应该是这样的:
class Widgets extends Controller {
private $guzzle;
public function __construct(GuzzleHttp\Client $guzzle)
{
$this->guzzle = $guzzle;
}
public function index(){
// Stuff
$url = "api.example.com";
$response = $this->guzzle->request('POST', $url, ['body' => array(...)]);
// More stuff
}
}
Run Code Online (Sandbox Code Playgroud)
现在你的测试应该更容易编写.您可以在测试时将模拟Guzzle对象传递到您的类中.
现在,您可以只观看您的模拟类,以确保对它的调用与Guzzle API为了拨打电话而预期接收的内容相匹配.
如果你班级的其余部分取决于从Guzzle收到的输出,那么你也可以在你的模拟中定义.
归档时间: |
|
查看次数: |
5490 次 |
最近记录: |