Testing external APIs is like trying to test your car while stuck in traffic - unpredictable and frustrating. Laravel's Http::fake()
is your test track where everything works perfectly:
Use Http::fake()
to mock HTTP responses in your tests:
use Illuminate\Support\Facades\Http;
// In your test
public function test_user_can_fetch_external_data()
{
// Fake all HTTP requests
Http::fake([
'api.example.com/*' => Http::response([
'users' => [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane']
]
], 200),
'payments.stripe.com/*' => Http::response([
'status' => 'success',
'payment_id' => 'pay_123'
], 200)
]);
// Your code that makes HTTP requests
$response = $this->post('/api/sync-users');
$response->assertStatus(200);
// Assert HTTP requests were made
Http::assertSent(function ($request) {
return $request->url() === 'https://api.example.com/users';
});
}
Different faking strategies:
// Fake all requests with same response
Http::fake();
// Fake specific URLs
Http::fake([
'github.com/*' => Http::response(['name' => 'Laravel'], 200),
'api.stripe.com/*' => Http::response(['error' => 'Invalid key'], 401),
]);
// Fake with callbacks
Http::fake(function ($request) {
if ($request->url() === 'https://api.example.com/users') {
return Http::response(['users' => []], 200);
}
return Http::response([], 404);
});
// Fake sequences for multiple calls
Http::fake([
'api.example.com/*' => Http::sequence()
->push(['status' => 'pending'], 200)
->push(['status' => 'completed'], 200)
->pushStatus(404)
]);
Table Of Contents
Behind the Scenes
When you call Http::fake()
, Laravel intercepts any outgoing HTTP requests and serves your predefined responses instead. It's like having a mock server that always gives you exactly what you expect - no network delays, no API limits, no service outages.
Complete testing example:
public function test_api_service_handles_failures_gracefully()
{
// Mock API failure
Http::fake([
'api.external.com/*' => Http::response([], 500)
]);
// Test your service
$service = new ExternalApiService();
$this->expectException(ApiException::class);
$service->fetchUserData();
// Verify the request was attempted
Http::assertSent(function ($request) {
return str_contains($request->url(), 'api.external.com/users');
});
// Verify headers were sent correctly
Http::assertSent(function ($request) {
return $request->hasHeader('Authorization', 'Bearer test-token');
});
}
// Test multiple requests
public function test_service_makes_correct_api_calls()
{
Http::fake();
$service = new UserSyncService();
$service->syncUsers();
// Assert specific requests were made
Http::assertSentCount(2);
Http::assertSent(fn($request) => $request->url() === 'https://api.users.com/list');
Http::assertSent(fn($request) => $request->url() === 'https://api.profiles.com/batch');
Http::assertNotSent(fn($request) => str_contains($request->url(), 'analytics.com'));
}
Related: Laravel Collections: Beyond Basic Array Operations | Unit Testing Tutorial for Beginners | Laravel Testing: Unit, Feature and Integration Tests | Laravel Testing: Unit, Feature and Integration Tests | Laravel Dusk: Browser Testing Advanced Techniques
Add Comment
No comments yet. Be the first to comment!