Implementation worksheet · 5 min read
How to Test an App When Its Third-Party API Is Unavailable
Simulate four failure modes rather than waiting to meet them: hard failure (connection refused or 503), slow failure (responses at or beyond your timeout — the one that actually takes apps down), partial failure (200 with a malformed or empty body), and rate limiting (429 with a Retry-After header). Force each by pointing the integration at a local stub you control rather than by unplugging anything: a stub that can be told to hang for 30 seconds, return 503, or return `{}` gives you all four on demand. Then assert on user-visible behaviour, not logs — the question is whether the page still renders, the queue still drains, and the retry does not become a storm.
Every integration works when the vendor is up. Testing the other state is skipped because it feels like testing someone else's software — but you are testing your own behaviour under their failure, which is entirely yours to get right.
Put it into practice
1. Point the integration at a stub you control
One environment variable switching the base URL to a local stub is all the setup needs. Recorded fixtures are fine for the happy path; the stub exists to produce failures on demand, which recordings cannot.
2. Test slow before you test down
A vendor returning 503 is easy — your code sees an error. A vendor taking 45 seconds is the one that exhausts your connection pool and takes the whole app down with it. Every outbound call needs an explicit timeout; the test is whether one exists and is shorter than your own request budget.
3. Test the partial response
200 with an empty body, a missing field, or a string where a number belongs. Generated integration code parses optimistically and throws inside the happy path, which usually surfaces as a 500 on a page that had nothing to do with the vendor.
4. Test 429 and honour Retry-After
Confirm you back off rather than retry immediately, and that the backoff is per-operation rather than global. Then check the multiplier: three retries across five parallel workers is fifteen requests at a vendor that just asked you to slow down.
5. Assert on what the user sees
For each failure: does the page still render, is the message honest and actionable, is queued work preserved, and does the system recover on its own when the vendor returns? A retry that needs a human to restart it is not a retry.
Failure simulation matrix
Copy this structure into your review document and record your observed result for each row.
| Failure | How to force it | Expected behaviour | Verified |
|---|---|---|---|
| Hard down | stub returns 503 | degrade per contract, no 500 page | |
| Slow | stub sleeps past timeout | timeout fires, request budget held | |
| Partial | stub returns {} or wrong type | handled, user sees honest state | |
| Rate limited | stub returns 429 + Retry-After | backoff honoured, no storm | |
| Recovery | stub restored | queue drains without intervention |
A failure worth checking
The retry storm: the vendor wobbles, every worker retries three times immediately, and your traffic multiplies at exactly the moment the vendor is least able to serve it — turning their brief degradation into your sustained outage, and sometimes extending theirs. Backoff with jitter, a cap on attempts, and a circuit breaker after repeated failures are the three lines that prevent it, and none of them are generated unless you ask.
Common questions
Can I test this against the vendor's sandbox?
Sandboxes model the happy path and occasionally a declined card. They do not let you force a 45-second response or a truncated body, which are the cases that hurt. Use the sandbox for correctness and a stub for failure.
How often should these tests run?
In CI on every change to integration code, and again whenever a vendor announces an API version change. The matrix is five cases; keeping it green costs minutes and catches the regression where someone removes a timeout.
Basis and scope
This is a proposed implementation method using illustrative examples, not a measured benchmark or a customer case study. Prepared with AI assistance. Validate product-specific behavior against current documentation and your own test environment.