Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here
Premium Members Only
Join to unlock this tutorial and all of our courses.
Tutorial Premium Tutorial

Laravel Testing: Mocking/Faking External 3rd Party APIs

January 05, 2023
11 min read

Laravel PHPUnit Mocking

One of the most common questions about automated testing in Laravel is how to write tests for the usage of some external API. There are three ways to do that, and I will show all of those in this article.

This is a text-based excerpt of one chapter in my course Advanced Laravel Testing

We will talk about:

  • Faking HTTP requests
  • Mocking Classes
  • Using External Sandboxes

As an example, let's imagine you use an external service to get the information by IP address, with Laravel HTTP Client.

1private static function getIpData(string $ip): array
2{
3 $token = config('location.ipdata.token', '');
4 
5 $url = "https://api.ipdata.co/{$ip}?api-key=".$token;
6 
7 return Http::get($url)->throw()->json();
8}

How would you test if it works?

The code above is from a real open-source project Monica. Let's take a look at our options.


Option 1. Faking HTTP Requests with Http::fake()

The project authors fake the HTTP requests for external services.

They also use a thing called Fixtures, which are just pre-prepared sets of data. So, if we take a look at tests/Fixtures, there are prepared sets of data in JSON format. Ipdata.json contains an example response from an external service about IP. So, the IP address should contain this example information:

1{
2 "ip": "12.34.56.78",
3 "is_eu": true,
4 "city": "Paris",
5 "region": "\u00cele-de-France",
6 "region_code": "IDF",
7 "country_name": "France",
8 "country_code": "FR",
9 "continent_name": "Europe",
10 "continent_code": "EU",
11 "latitude": 0,
12 "longitude": 0,
13 "postal": "75000",
14 "calling_code": "33",
15 "flag": "https://ipdata.co/flags/fr.png",
16 "emoji_flag": "\ud83c\uddeb\ud83c\uddf7",
17 "emoji_unicode": "U+1F1EB U+1F1F7",
18 "languages": [
19 {
20 "name": "French",
21 "native": "Fran\u00e7ais"
22 }
23 ],
24 "currency": {
25 "name": "Euro",
26 "code": "EUR",
27 "symbol": "\u20ac",
28 "native": "\u20ac",
29 "plural": "euros"
30 },
31 "time_zone": {
32 "name": "Europe/Paris",
33 "abbr": "CET",
34 "offset": "+0100",
35 "is_dst": false,
36 "current_time": "2021-11-01T00:00:00+01:00"
37 },
38 "threat": {
39 "is_tor": false,
40 "is_proxy": false,
41 "is_anonymous": false,
42 "is_known_attacker": false,
43 "is_known_abuser": false,
44 "is_threat": false,
45 "is_bogon": false
46 },
47 "count": "0"
48}

Now, how those example JSON responses are used in tests? This ipdata.json file usage can be found in the tests/Unit/Helpers/RequestHelperTest.php method get_infos_from_ip():

1class RequestHelperTest extends TestCase
2{
3 /** @test */
4 public function get_infos_from_ip()
5 {
6 config(['location.ipdata.token' => 'test']);
7 
8 $body = file_get_contents(base_path('tests/Fixtures/Helpers/ipdata.json'));
9 Http::fake([
10 'https://api.ipdata.co/*' => Http::response($body, 200),
11 ]);
12 
13 $this->assertEquals(
14 [
15 'country' => 'FR',
16 'currency' => 'EUR',
17 'timezone' => 'Europe/Paris',
18 ],
19 RequestHelper::infos('test')
20 );
21 }
22}

Now, what does this test do?

First, it overwrites the config, so we don't expose and don't use the live token of that service ipdata.co.

Then, we use Http::fake(). So you can fake the request to any URL, here https://api.ipdata.co/* they use asterisks so that whatever URL with api.ipdata.co would be faked with the response. That response comes from the ipdata.json you saw earlier.

So we fake the API request to api.ipdata.co so it would not make the real HTTP request, but instead...

Premium Members Only

This advanced tutorial is available exclusively to Laravel Daily Premium members.

Premium membership includes:

Access to all premium tutorials
Video and Text Courses
Private Discord Channel

Comments & Discussion

VR
Vijay Rana ✓ Link copied!

Been stucked at this. Thank you for the article!!!

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.