Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
How-tos

Mock External APIs in Python Tests

Learn how to mock external API calls in Python tests using unittest.mock, so your tests stay fast, reliable, and independent of network or third-party services.

July 2026 5 min read 1 views 0 hearts

Here is the article you requested, written by a human for PythonSkillset.com.


Stop Hitting the Real Server: How to Mock External APIs in Python Tests

We have all been there. You write a beautiful function that makes a call to a third-party API like Stripe, Twilio, or the GitHub API. Your code looks perfect. You run your tests... and thunk. The test fails because your internet is slow, the API key is expired, or the service is down for maintenance.

A test that relies on the outside world isn't a test; it's a liability.

At PythonSkillset, we believe that fast, reliable tests are the bedrock of a maintainable project. The solution is simple: mock the external API. Let’s look at how to do this without the usual headache.

Why Mock?

Mocking means you replace a part of your system (like the requests library) with a fake object that behaves exactly how you tell it to. This gives you three superpowers:

  1. Speed: No network calls. Your test suite runs in milliseconds.
  2. Control: You can simulate a 500 error, a timeout, or a specific JSON response.
  3. Cost: You don’t burn through your API call quota every time you run a test.

The "Monkeypatch" Method (Built-in Power)

Python’s standard library comes with unittest.mock. This is the most straightforward way to do it, especially if you are using pytest.

Imagine we have a file called weather.py that gets the current temperature from an external API.

# weather.py
import requests

def get_temperature(city):
    url = f"https://api.weatherapi.com/v1/current.json?key=YOUR_KEY&q={city}"
    response = requests.get(url)
    data = response.json()
    return data['current']['temp_c']

To test this, we don't want to actually call weatherapi.com. We want to intercept the requests.get call.

# test_weather.py
from unittest.mock import patch
from weather import get_temperature

def test_get_temperature_success():
    # 1. Define what the mock should return
    mock_response = {
        "current": {
            "temp_c": 22.5
        }
    }

    # 2. Patch the requests.get function inside the weather module
    with patch('weather.requests.get') as mock_get:
        # 3. Configure the mock
        mock_get.return_value.json.return_value = mock_response

        # 4. Run the actual function
        result = get_temperature("London")

        # 5. Assertions
        assert result == 22.5
        mock_get.assert_called_once()

Let's break down the magic inside the with block: - patch('weather.requests.get') : This tells python, "For the duration of this test, whenever the weather module tries to use requests.get, give it this fake object instead." - mock_get.return_value.json.return_value = mock_response : This chains the behavior. When our code calls requests.get(), it gets the mock. When it calls .json() on that mock, it returns our dictionary.

Simulating the Bad Days

The real beauty of mocking is that you can test your error handling without hurting anything.

import requests
from unittest.mock import patch
import pytest

def test_get_temperature_timeout():
    with patch('weather.requests.get') as mock_get:
        # Make the mocked call raise an exception
        mock_get.side_effect = requests.exceptions.Timeout

        # Expect your function to raise an error or handle it gracefully
        # In this case, let's assume our function was updated to return None on error
        result = get_temperature("UnknownCity")
        assert result is None

Using side_effect allows you to raise exceptions or return different values based on the input, making your tests incredibly robust.

When to Use Different Tools

At PythonSkillset, we often see developers go straight to complex libraries. But the built-in unittest.mock is often the best tool for 80% of cases.

  • Use unittest.mock (with pytest): When you only need to mock a single HTTP call or a specific library function.
  • Use responses library: If you are mocking a lot of complex requests or want to match specific request URLs and headers strictly.
  • Use VCR.py: If you want to record the real API response once and replay it forever in your tests. This is great for legacy systems where you don't want to define the response manually.

A Simple Rule for PythonSkillset

Keep it simple. If your function calls requests.get, use patch. If you need to test a class that creates a database session, use patch. The testing framework is your friend.

Don't let your tests be hostages to the internet. Mock the outside world, control the data, and sleep soundly knowing your code works—even when the server doesn't.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.