Integration tests that call real third-party APIs break for reasons that have nothing to do with your code: the API is slow, rate-limits your runner, changes its data, or is down. A mock API fixes that, but "mock API" covers three quite different setups. Picking the right one matters more than picking a brand.
The three ways to mock an API in CI
1. In-process mocks: MSW, nock
The mock lives inside your test process and intercepts requests before they leave it. Nothing to start, nothing on the network, and it's as fast and deterministic as it gets.
- Best for: unit and component tests, and frontend tests in Jest, Vitest or Playwright component mode.
- Limits: it only works inside the process that installed it. It can't serve a separate service, a mobile app, a Postman collection or a script in another language.
2. Local mock servers in the pipeline: WireMock, Mockoon CLI, json-server
You start a mock server as a step or service container in the CI job, and your tests call it over localhost.
- WireMock runs as a standalone JAR or Docker image, with request matching, stateful scenarios, fault injection and record-and-playback.
- Mockoon lets you design mocks in a desktop app and run the exported environment headless with its CLI.
- json-server turns a JSON file into a REST API in seconds.
- Best for: contract-style tests against an API you control, and suites that must never touch the network.
- Limits: you write and maintain the stubs, and keep them in step with the real API.
3. Hosted mock APIs: ReqRes, Beeceptor, Postman mock servers
A public URL that returns realistic responses, with nothing to run.
- Best for: teaching, demos, examples in docs, smoke tests of an HTTP client, and anything outside your codebase that needs a real URL (mobile builds, low-code tools, AI agents).
- Limits: your tests now depend on the network and on someone else's uptime and rate limits. Use a personal key, and keep the number of calls per run small.
Making a hosted mock API CI-safe
If you use a hosted mock in CI, three things keep it stable:
Deterministic data. Responses should be identical on every run. With ReqRes's Agent Sandbox, pass a seed and you get byte-identical data every time; the
X-World-Versionheader tells you if the fixture world ever changes:curl "https://reqres.in/agent/v1/users?seed=42&limit=5"Your own key and known limits. Hosted CI runners share IP addresses, so anonymous per-IP limits get used up by other people's builds. Send a personal key: a free ReqRes account gives you 250 requests a day on the classic endpoints, and Lite raises that to 10,000. The Agent Sandbox allows 100 requests a day per IP on the free tier.
Failures on purpose. Test the unhappy path with predictable failures rather than waiting for real ones. ReqRes has 15 failure scenarios; three are free (
rate-limitedreturns a 429 withRetry-After,validation-errora 422, andmalformed-jsona 200 with a truncated body), and the rest (timeouts, 5xx, payment declines) are on paid plans.
Which should you use?
| You need | Use |
|---|---|
| Fast, offline mocks inside JS/TS tests | MSW |
| A stubbed version of your own API, no network in CI | WireMock or Mockoon CLI |
| A quick fake REST API from a JSON file | json-server |
| A real URL with realistic data, nothing to run | A hosted mock such as ReqRes |
| Deterministic fixtures and failure scenarios over HTTP | ReqRes Agent Sandbox (seeded) |
Many teams use more than one: MSW for component tests, and a local or hosted mock for the end-to-end smoke test that proves the real HTTP stack works.
We make ReqRes, so weigh our section accordingly. More: ReqRes for error-handling tests and API testing in CI/CD.