带PHPUnit的Laravel控制器内部单元测试
我不太确定在这种情况下采用哪种方法进行单元测试。对于我来说,单元测试Guzzle的示例中没有一个对如何在这个场景中实现有意义,或者可能我只是错误地看待了它 设置:Laravel 4.2 REST API-控制器方法在方法中使用Guzzle从另一个API请求数据,如下所示:带PHPUnit的Laravel控制器内部单元测试,php,unit-testing,laravel,phpunit,guzzle,Php,Unit Testing,Laravel,Phpunit,Guzzle,我不太确定在这种情况下采用哪种方法进行单元测试。对于我来说,单元测试Guzzle的示例中没有一个对如何在这个场景中实现有意义,或者可能我只是错误地看待了它 设置:Laravel 4.2 REST API-控制器方法在方法中使用Guzzle从另一个API请求数据,如下所示: <?php class Widgets extends Controller { public function index(){ // Stuff $client = new
<?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
}
}
?>
然而,Guzzle仍在向外部服务发出实际的HTTP请求。我的猜测可能是通过某种方式将Controller方法中的客户端创建设置为使用$handler,但我无法想象这是正确的方法。我错过了什么
编辑
我的解决方案如下:
<?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
}
}
?>
这种解决方案感觉最正确,而且是拉雷维尔式的。()
我会在每个api调用上面添加这个(根据api调用中需要模拟的外部调用的数量更改模拟响应)
如果控制器需要Guzzle客户端,我将其添加到控制器:
public function __construct(GuzzleHttp\Client $client)
{
$this->client = $client;
}
然后将$this->client用于所有api调用。使用包。它有助于记录和重播HTTP请求。通过Guzzle测试api调用非常方便,对此的“经典TDD”响应是根本不应该对Guzzle进行单元测试。Guzzle是一个第三方库,它应该由自己的开发者进行充分的测试
您需要测试的是您的代码是否正确调用Guzzle,而不是当您的代码调用Guzzle时Guzzle是否工作
方法如下:
<?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
}
}
?>
与其在控制器中执行new Guzzle()
,不如使用依赖项注入将Guzzle对象传递到控制器中。幸运的是,拉雷维尔让这变得非常容易;您所需要做的就是为控制器类提供一个构造函数方法,并将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
}
}
现在,您的测试应该更容易编写。您可以在测试时将模拟Guzzle对象传递到类中
现在,您只需观察您的mock类,以确保对它的调用与Guzzle API期望接收到的调用相匹配
如果类的其余部分依赖于从Guzzle接收的输出,那么您也可以在模拟中定义它。如果有人正在努力解决这个问题,那么我发现:
$this->app->bind('MyController', function($app){
与
在Laravel 5.5.44中为我做了这个把戏是正确的,我对测试Guzzle一点也不感兴趣,我只是希望$client->request(…)调用不被执行,只返回一些模拟数据,就好像它是成功的还是失败的——这取决于我正在进行的单元测试。今天晚些时候我要试试这个。谢谢这绝对是我认为首选的方法。这感觉最自然,因为我最终在拉雷维尔使用了IoC容器。我用我的最终答案更新了我的问题。这是一个有趣的方法。今天晚些时候我会调查的。谢谢
$this->app->bind(MyController::class, function($app){