Mocking external API calls
Overview
**Memorizable line:** Mocking an API means replacing a slow internet request with a fake, instant response. When we write tests, we do not want to actually call outside APIs like Google or Stripe. It is slow, costs money, and requires internet. Instead, we `mock` the API call. Here is a function that gets a user profile from an API. ```python import requests def get_profile(user_id): response = requests.get(f'http://api.com/{user_id}') return response.json() ``` We can use `patch` to mock `requests.get`. We give it a fake response that acts like the real one. ```python from unittest.mock import patch, Mock @patch('__main__.requests.get') def test_profile(mock_get): fake_response = Mock() fake_response.json.return_value = {'name': 'Rahul'} mock_get.return_value = fake_response assert get_profile(1)['name'] == 'Rahul' ``` **Analogy:** Think of a fire drill. You do not start a real fire to test the alarm. You use a smoke machine to fake the fire. Mocking is the smoke machine for your code.
It keeps tests fast, free, and reliable. Your tests will pass even without internet.
Where used: pytest, unittest
Why learn this
- Allows you to test code that uses the requests library safely.
Code walkthrough
from unittest.mock import Mock
def get_data(api_call):
resp = api_call()
return resp.json()
fake_api = Mock()
fake_api.return_value.json.return_value = 'data'
print(get_data(fake_api))
Focus: fake_api.return_value.json.return_value = 'data'
Aha moment
from unittest.mock import Mock
mock_obj = Mock()
mock_obj.some_method.return_value = 42
print(mock_obj.some_method())
Prediction: What does this print?
Common guess: An error, because some_method does not exist.
A Mock object magically accepts any method call you invent and returns what you tell it to.
Common mistakes
- Forgetting to mock the JSON method: APIs return a response object. You must mock both the response object AND its `.json()` method.
Recall questions
- Explain mocking an API in your own words, as if to a classmate.
- Why do we mock external APIs in tests?
Understanding checks
What prints, and why?
ok
The fake response was set up so its `.json()` method returns a dictionary with 'status': 'ok'.
Where is the bug?
fake_resp.return_value is set, but it should be fake_resp.json.return_value.
The real code calls `.json()`, so we must mock the return value of the `json` method, not the response object itself.
Practice tasks
Mock a response
Given this working code, change `fake_resp.json.return_value` so that the printed name is 'Amit'.
Challenge
Create a fake response
Create a `Mock` object called `response`. Set its `status_code` attribute to `200` and make its `.json()` method return `['apple']`.
Continue learning
Previous: patch as decorator and context manager