We test with external services to check if our code works well when it talks to other programs or websites.
Testing with external services in PyTest
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
PyTest
import pytest import requests from unittest.mock import patch @patch('requests.get') def test_external_service(mock_get): mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = {'key': 'value'} response = requests.get('https://api.example.com/data') assert response.status_code == 200 assert response.json() == {'key': 'value'}
Use @patch to replace the real external call with a fake one during tests.
This helps tests run fast and not depend on the real service being available.
Examples
PyTest
from unittest.mock import patch @patch('requests.post') def test_post_service(mock_post): mock_post.return_value.status_code = 201 response = requests.post('https://api.example.com/create') assert response.status_code == 201
PyTest
import pytest import requests @pytest.mark.skip(reason='External service not available') def test_real_service_call(): response = requests.get('https://api.example.com/data') assert response.status_code == 200
Sample Program
This test replaces the real HTTP GET call with a fake one that returns a fixed response. It then checks if the code correctly handles that response.
PyTest
import pytest import requests from unittest.mock import patch @patch('requests.get') def test_fetch_data(mock_get): # Setup mock response mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = {'name': 'Test User', 'id': 123} # Call the function that uses requests.get response = requests.get('https://api.example.com/user') # Check the response assert response.status_code == 200 assert response.json() == {'name': 'Test User', 'id': 123}
Important Notes
Always mock external services in tests to avoid slow or unreliable tests.
Use unittest.mock.patch to replace external calls with fake responses.
Test how your code handles errors like timeouts or bad responses from external services.
Summary
Testing with external services means faking those services during tests.
This makes tests faster and more reliable.
Use mocking tools like patch to do this easily.
Practice
1. What is the main reason to use mocking when testing with external services in pytest?
easy
Solution
Step 1: Understand the role of mocking in tests
Mocking replaces real external calls with fake ones to avoid delays and failures.Step 2: Identify the benefit of mocking external services
Mocking makes tests faster and more reliable by not depending on real services.Final Answer:
To avoid calling the real external service and make tests faster -> Option AQuick Check:
Mocking speeds up tests by faking external calls [OK]
Hint: Mock external calls to speed tests and avoid failures [OK]
Common Mistakes:
- Thinking mocking increases real API calls
- Believing tests should depend on internet speed
- Confusing testing external service with testing your code
2. Which of the following is the correct way to mock a function
get_data from module external_api using pytest's patch decorator?easy
Solution
Step 1: Recall correct patch syntax
The patch decorator requires the full import path as a string: 'module.function'.Step 2: Match the correct option
@patch('external_api.get_data') uses 'external_api.get_data' which is the correct format and case-sensitive.Final Answer:
@patch('external_api.get_data') -> Option AQuick Check:
patch('module.function') syntax is correct [OK]
Hint: Use 'module.function' string in patch decorator [OK]
Common Mistakes:
- Swapping module and function order
- Using wrong separators like '->'
- Incorrect function name casing
3. Given the following pytest test code, what will be the output when running the test?
from unittest.mock import patch
import requests
def fetch_status():
response = requests.get('https://api.example.com/data')
return response.status_code
@patch('requests.get')
def test_fetch_status(mock_get):
mock_get.return_value.status_code = 200
assert fetch_status() == 200
print('Test passed')medium
Solution
Step 1: Understand mocking effect on requests.get
The patch replaces requests.get with a mock that returns an object with status_code 200.Step 2: Check assertion and print statement
fetch_status() returns 200, matching the assertion, so 'Test passed' is printed.Final Answer:
Test passed -> Option CQuick Check:
Mocked return_value.status_code = 200 makes test pass [OK]
Hint: Mock return_value to control function output [OK]
Common Mistakes:
- Forgetting to set return_value.status_code
- Expecting real HTTP call instead of mock
- Missing print output due to assertion failure
4. Identify the error in the following pytest test that mocks an external service call:
from unittest.mock import patch
import myservice
@patch('myservice.call_api')
def test_api(mock_call):
mock_call.return_value = {'status': 'ok'}
result = myservice.call_api()
assert result.status == 'ok'medium
Solution
Step 1: Analyze the mocked return value type
The mock returns a dictionary {'status': 'ok'}, so result is a dict.Step 2: Check the assertion syntax
Accessing dict keys requires bracket notation, not dot notation; result.status causes AttributeError.Final Answer:
The assertion should use result['status'] instead of result.status -> Option BQuick Check:
Dict keys need brackets, not dot notation [OK]
Hint: Use brackets for dict keys in assertions [OK]
Common Mistakes:
- Using dot notation on dicts
- Forgetting parentheses in patch decorator (not here)
- Expecting return_value must be string always
5. You want to test a function
process_data() that calls an external API fetch_data(). The API sometimes returns null. How should you mock fetch_data in pytest to test process_data handles null correctly?hard
Solution
Step 1: Understand the need to test null handling
Since fetch_data can return null, tests must simulate this to check process_data behavior.Step 2: Use patch to mock fetch_data returning null
Mocking fetch_data to return null allows controlled testing of process_data's handling of that case.Final Answer:
Use patch to make fetch_data return null and assert process_data handles it -> Option DQuick Check:
Mock null return to test edge case handling [OK]
Hint: Mock edge cases like null to test error handling [OK]
Common Mistakes:
- Calling real external API in tests
- Mocking only success cases, ignoring null
- Ignoring exceptions instead of testing them
