Interview frequency: …
Short answer
Test the client through a fake transport or fake server, simulating failure cases (timeouts, 5xx, invalid payloads), then add a limited number of contract or integration tests against the real service.
Explanation
The real network adds slowness, instability, and dependence on an external service's state. Libraries such as httpx provide MockTransport, and tools like respx and responses intercept requests. Do not let the fake always return success; the test's value lies in checking error handling, retries, and data conversion. Block real connections in tests by default (for example with pytest-socket) so they cannot leak through.
Code example
import httpx
def handler(request: httpx.Request) -> httpx.Response:
if request.url.path == "/users/1":
return httpx.Response(200, json={"id": 1, "name": "Omar"})
return httpx.Response(503)
def test_get_user():
client = httpx.Client(transport=httpx.MockTransport(handler), base_url="https://api.test")
assert UserClient(client).get(1).name == "Omar"
def test_service_unavailable():
client = httpx.Client(transport=httpx.MockTransport(handler), base_url="https://api.test")
with pytest.raises(ServiceUnavailable):
UserClient(client).get(2)Common mistakes
- Tests that call real APIs and fail when the internet drops or the data changes.
- Testing only the success path and ignoring timeouts and server errors.
Follow-up questions
- What is the difference between unit tests and integration tests?
- How do you test asynchronous (async) code?