#phpunit #guzzle #laravel-8
#phpunit #guzzle #laravel-8
Вопрос:
Я создаю модульные тесты в Laravel 8 с помощью phpunit, и у меня есть контроллер, который использует внешний API для получения данных для моих функций с помощью HTTP-клиента Guzzle.
Я поместил метод для вызова guzzle внутри Controller.php
, чтобы к нему можно было получить доступ в любом другом контроллере, расширив этот класс
class Controller extends BaseController
{
protected function getAPI($url, $params = [])
{
$test_api = new Client();
$headers = [
'form_params' => $params,
'http_errors' => false
];
$response = $test_api->get($url, $headers);
// More stuff to get the response...
}
}
На других контроллерах я вызвал метод для выполнения вызова API
class OtherController extends Controller
{
public function someMethod()
{
$response = $this->getAPI('/get_data', [], 'get');
// More stuffs...
}
}
Модульный тест, который я создаю, предназначен для someMethod()
, и я не знаю, как имитировать вызов API внутри этого контроллера, который был расширен на другом контроллере.
Я хотел имитировать вызов API, поэтому мне не нужно на самом деле «вызывать» API. Я проверил документацию guzzle о тестировании (https://docs.guzzlephp.org/en/stable/testing.html#mock-handler ) но это не имеет смысла в том, как реализовать это в моем сценарии.
Ответ №1:
Вы можете использовать PHPUnit:
use TestsTestCase;
[...]
public function testApiOtherControllerSomeMethod(){
//Prepare your sample data that mocks API result
//or create a variable with your wanted api mocked data.
$apiTestData = Storage::disk('test-data-api')
->get('apiTestData.txt');
//Using the PHPUnit MockBuilder, target the class and method
//you want to mock. In your case, you mock the inherited method
//"getAPI" from Controller, in OtherController
$apiMock = $this->getMockBuilder(OtherController::class)
->onlyMethods(['getAPI'])
->getMock();
//use the mock object to change the method's return output
$apiMock->expects($this->any())
->method('getAPI')
->willReturn($apiTestData);
//now the mock object will behave like the OtherController class
//and you can now call "someMethod", which will return the mocked
//data when calling getAPI() internally.
$testResult = $apiMock->someMethod();
//$this->assert... your returned mocked data.
}
В качестве примечания, вам, вероятно, следует перенести обработку API из основного класса контроллера в службу API.