My API code
public function store (Request $request, $profileId)
{
$all = $request->all();
$token = AccessToken::with('users')->where('access_token',$request->input('access_token'))->first();
if($token && $token->users->isOwnProfile($profileId))
{
$rules = [
'access_token' => 'required',
'title' => 'required',
'description' => 'required',
'file_id' => 'required',
'audience_control' => 'required|in:' . join(',', PostRepository::$AUDIENCE_CONTROL),
'tags' => 'required',
];
$validator = Validator::make($all, $rules);
$error = $validator->errors()->toArray();
if ($validator->fails())
{
return $this->setStatusCode(401)
->setStatusMessage(trans('api.validation failed'))
->respondValidationMessage($error);
}
try {
$response = $this->postRepository->save($request, $profileId);
if(isset($response['error']))
return $this->messageSet([
'message' => $response['error']['message'],
], $response['error']['status_code']);
return $this->setDataType('post_id')
->setStatusCode('200')
->respondWithCreatedId(trans('api.Post created'), $response->id);
} catch (\Exception $e) {
return $this->respondInternalError(trans('api.processing error'));
}
}
return $this->respondInternalError('404 page');
}
From save method it calls another method that calls an external API.
/*
* this function returns some response where it has profile_id for
* the file which in other save function is matched that the
* profile_id passed as parameter is same with file profile_id
*/
public function getFileDetails($file_id)
{
try
{
$response = json_decode((new Client())->request('GET', env('xyz','http://abc.xyz/api/v1').'/files/' . $file_id)->getBody()->getContents(), true);
}
catch (RequestException $e)
{
$response = json_decode($e->getResponse()->getBody()->getContents(), true);
}
return $response;
}
Now this is my test function for API.
public function testPostCreateChecksProfileMatchesCorrectly()
{
$this->json('POST', 'profiles/' . $this->getProfile()->id . '/posts' . '?access_token=' . $this->getAccessToken(), [
'title' => 'api testing title',
'description' => 'api testing description',
'audience_control' => 'public',
'tags' => [
'Animals',
'City'
],
'file_id' => '281'
])->seeJsonStructure([
'success' => [
'message',
'post_id',
'status',
],
]);
}
Now my question is how can I create a fake response for the external API when I am testing.
I am using PHPUnit
& Laravel 5.2
.
You can use PHP VCR to record the output of the API request.
https://github.com/php-vcr/php-vcr.
With this package, you will be able to save it in the tests/fixtures directory.
So after the first time, PHPUnit will read this file instead of doing other requests.
And in this way will be added also to your GIT repo.
First you need to install it using:
composer require php-vcr/php-vcr
composer require php-vcr/phpunit-testlistener-vcr
The second package integrates PHPUnit with PHP-VCR.
Then add to your phpunit.xml after
<listeners>
<listener class="VCR\PHPUnit\TestListener\VCRTestListener" file="vendor/php-vcr/phpunit-testlistener-vcr/src/VCRTestListener.php" />
</listeners>
Then create the dir called 'fixtures' in the tests directory of your Laravel application.
Now we can test like:
/** @test */
public function itShouldGetVenueGpsCoordinates()
{
$address = "Milano, viale Abruzzi, 2";
VCR::turnOn();
VCR::insertCassette('mapquestapi');
$coordinates = $this->venueService->getVenueGpsCoordinates($address);
VCR::eject();
VCR::turnOff();
$this->assertEquals(45, number_format($coordinates['lat'], 0));
$this->assertEquals(9, number_format($coordinates['lng'], 0));
}
The test will create then a fixture, in my case called 'mapquestapi', that you will be able to add to your GIT repo. So from the second time, the API will be called by your test, the data will be loaded from this file instead of making a new request.
If you are subscribed to Laracast you can see a complete video tutorial here. https://laracasts.com/lessons/testing-http-requests
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With