I mock at the HTTP boundary, not my own function, so parsing, timeouts and retry are tested too.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # ====================================================================== # Q: How do you mock an external HTTP API (e.g. a courier or payment gateway)? # # I mock at the HTTP boundary, not my own function, so parsing, timeouts and # retry are tested too. I always test the unhappy paths: 5xx, timeout, invalid # JSON, 429 with Retry-After. Most production bugs in the e-shops came from # there. # ====================================================================== # httpx -> respx import httpx, respx @respx.mock def test_courier_label_retry_on_503(): route = respx.post('https://api.courier.gr/v2/labels').mock(side_effect=[ httpx.Response(503), httpx.Response(201, json={'tracking': 'GR123'}), ]) assert create_label(order_id=5) == 'GR123' assert route.call_count == 2 # requests -> responses import responses @responses.activate def test_payment_declined(): responses.post('https://pay.example.com/charges', json={'status': 'declined', 'code': 'insufficient_funds'}, status=402) with pytest.raises(PaymentDeclined): charge(order_id=5, amount_cents=1999) |