- Setting up a Laravel Test
- Using Http::fake to Fake API Responses
- Faking Specific Endpoints and Responses
- Summary
Testing is a crucial aspect of any application's development process. In Laravel, it's easy to write tests for various parts of your application, including API interactions. When testing APIs, you might need to fake responses to ensure your tests are fast, reliable, and independent of external factors. In this blog post, we'll dive into using Laravel's Http::fake
method to fake API responses during testing, complete with code examples to help you get started.
While Laravel has great documentation, its docs on HTTP tests don't go into much detail on the method below.
Setting up a Laravel Test
Before diving into Http::fake
, let's quickly set up a test in Laravel. If you haven't already, create a new Laravel project using Composer:
composer create-project --prefer-dist laravel/laravel my_project
Now, navigate to your project's root directory (cd my_project
) and create a new test class using the Artisan command:
php artisan make:test HttpFakeTest
We're using the traditional PHPUnit approach here to create a Feature test, but you can do something similar with Pest by adding --pest
. The actual test will differ with Pest though, so we'll stick with PHPUnit for this post. If you're interested in testing with Pest check out their section on Mocking, although it's not as clear as it could be on how to mock HTTP requests.
This command will generate a new test file named HttpFakeTest.php
in the tests/Feature
directory. Open this file and add the necessary imports at the top:
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
Http::fake
to Fake API Responses
Using Now that we have our test class set up, let's explore how to use Http::fake
to fake API responses.
Suppose you have a service class called WeatherService
that fetches weather data from an external API. Here's a simplified version of the WeatherService
class:
namespace App\Services;
use Illuminate\Support\Facades\Http;
class WeatherService
{
public function getWeatherData($city)
{
$response = Http::get("https://api.example.com/weather?city={$city}");
return $response->json();
}
}
To test the getWeatherData
method without making actual API calls, you can use Http::fake
to fake the response from the external API.
Here's an example of a test that uses Http::fake
to fake the weather API's response:
/** @test */
public function it_fakes_weather_api_response()
{
// Fake the API response
Http::fake([
'api.example.com/weather*' => Http::response([
'city' => 'New York',
'temperature' => 75,
'conditions' => 'Sunny'
], 200),
]);
// Instantiate the WeatherService class
$weatherService = new WeatherService();
// Call the getWeatherData method with a sample city
$response = $weatherService->getWeatherData('New York');
// Assertions
$this->assertSame('New York', $response['city']);
$this->assertSame(75, $response['temperature']);
$this->assertSame('Sunny', $response['conditions']);
}
In the test above, the Http::fake
method is used to define the fake API response for any request made to the api.example.com/weather*
endpoint. The Http::response
method is then used to create a fake response object with the desired data and status code.
In essence, Http::fake
instructs Laravel to intercept any outbound request to the endpoint you specify and instead response with the response you define.
When the getWeatherData
method is called within the test, it will receive the fake response instead of making an actual API call, allowing you to test your application's behaviour based on different API responses.
Faking Specific Endpoints and Responses
In some cases, you may want to fake responses for specific endpoints or conditions. To achieve this, you can use Http::fake
with a closure. The closure will receive the request object as an argument, allowing you to determine how to fake the response based on the request's properties.
For example, let's say you want to fake different responses depending on the city passed to the getWeatherData
method. Here's how you can achieve this:
/** @test */
public function it_fakes_weather_api_response_based_on_city()
{
// Fake the API response
Http::fake(function ($request) {
$url = $request->url();
if (strpos($url, 'New York') !== false) {
return Http::response([
'city' => 'New York',
'temperature' => 75,
'conditions' => 'Sunny',
], 200);
} elseif (strpos($url, 'London') !== false) {
return Http::response([
'city' => 'London',
'temperature' => 55,
'conditions' => 'Cloudy',
], 200);
}
return Http::response([], 404);
});
// Instantiate the WeatherService class
$weatherService = new WeatherService();
// Call the getWeatherData method with different cities
$responseNewYork = $weatherService->getWeatherData('New York');
$responseLondon = $weatherService->getWeatherData('London');
// Assertions for New York
$this->assertSame('New York', $responseNewYork['city']);
$this->assertSame(75, $responseNewYork['temperature']);
$this->assertSame('Sunny', $responseNewYork['conditions']);
// Assertions for London
$this->assertSame('London', $responseLondon['city']);
$this->assertSame(55, $responseLondon['temperature']);
$this->assertSame('Cloudy', $responseLondon['conditions']);
}
In this test, we use a closure with Http::fake
to inspect the request's URL and return a different fake response based on the city. This approach allows you to create more dynamic and context-aware fakes for your tests.
Summary
Faking API responses is an essential part of testing applications that interact with external APIs. Laravel's Http::fake
method makes it easy to fake responses for your tests, ensuring they remain fast, reliable, and independent of external factors.
By using Http::fake
, you can create simple or complex fake responses for your tests, allowing you to test your application's behaviour in various scenarios without making actual API calls. With this powerful tool at your disposal, you can write more robust and comprehensive tests for your Laravel applications.
There are a number of commonly used Facades within Laravel that can work in this way, the Http
client is just one of them. Another commonly used, tested and faked Facade within Laravel is the Storage
Facade. It too has a fake
method which can be used in a similar fashion.
Interested in proving your knowledge of this topic? Take the PHP Fundamentals certification.
PHP Fundamentals
Covering the required knowledge to create and build web applications in PHP.
$99