Reputation: 427
I'm creating unit tests in Laravel 8 using phpunit and I have a controller that uses external API to get data for my functions using Guzzle HTTP Client.
I placed the method to call the guzzle inside the Controller.php
so it can be accessed in any other controller by extending this class
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...
}
}
On other controllers I called the method to do the API call
class OtherController extends Controller
{
public function someMethod()
{
$response = $this->getAPI('/get_data', [], 'get');
// More stuffs...
}
}
The unit test I'm creating is for someMethod()
and I don't know how to mock the API call inside this controller that has been extended on other controller.
What I wanted is to mock the API call so I don't need to actually "call" the API. I checked the documentation of guzzle about testing (https://docs.guzzlephp.org/en/stable/testing.html#mock-handler) but it doesn't make sense on how to implement this on my scenario.
Upvotes: 2
Views: 2754
Reputation: 121
You can use PHPUnit:
use Tests\TestCase;
[...]
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.
}
As a side note, you should probably move the API handling from the main Controller class, into an API service.
Upvotes: 2