Bruno is a lightweight, Git-native, open-source API client, and that design keeps it fast and easy to version. But it leaves a gap teams hit fast: there’s no way to mock an endpoint that doesn’t exist yet. If you’ve searched for a Bruno mock server alternative, this guide explains why the gap exists, the workarounds people use, and how to generate a mock server straight from your OpenAPI spec.
Short answer up front: Bruno has no built-in mock server. You can send requests and write tests, but you can’t stand up a fake endpoint that returns sample responses. To mock, you reach for an external tool or hand-roll a server yourself.
Why you need a mock server
A mock server returns realistic responses for endpoints that aren’t built, aren’t stable, or are hard to trigger on demand. That unlocks a few things:
- Parallel development. Front-end and mobile teams build against the contract while the backend is still in progress. Nobody waits.
- Error-path testing. Real APIs rarely hand you a 429 or a 503 when you need one. A mock returns any status, header, or malformed body on command.
- Demos and prototypes. Show a working flow without a live backend, a database, or credentials.
- Stable CI. Tests that hit a mock don’t break because a staging server is down or rate-limited.
Here are failure scenarios a mock helps you test deliberately, instead of waiting for them to happen in production:
| Scenario | What the mock returns | Why it’s hard otherwise |
|---|---|---|
| Rate limit hit | 429 + Retry-After header |
Backend rarely throttles on demand |
| Server outage | 500 / 503 |
Can’t break staging just to test |
| Slow response | Delayed body | Hard to reproduce real latency |
| Empty result set | 200 with [] |
Depends on specific data state |
| Malformed payload | Body missing a required field | Backend validation usually prevents it |
Does Bruno have a mock server?
No. Bruno focuses on sending requests, organizing collections as plain files, and running assertions. There’s no native mock server, and no setting that turns a saved request into a live stub. That’s a deliberate scope choice, not an oversight, but it means mocking lives outside the tool.
In practice, Bruno users cover the gap two ways:
- External mocking tools. Stand up a separate service such as Mockoon, WireMock, Prism, or json-server, define responses there, then point Bruno at that URL. Two tools, two sources of truth.
- Hand-rolled servers. Write a small Express, Flask, or FastAPI app that returns canned JSON. Quick for one endpoint, tedious to maintain across a growing API.
Both work. Both add moving parts that live outside your collection.
The cost of bolt-on mocking
Stitching a separate mock layer onto Bruno is workable, but the cost shows up over time:
- Drift. Your spec, your Bruno requests, and your mock definitions live in three places. Change an endpoint and you update all three, or one silently goes stale.
- Setup tax. Every new teammate installs and configures the mock tool before they can run anything locally.
- Manual response writing. Hand-rolled servers mean writing example payloads by hand for every field and every status code.
- No realistic data. Static stubs return the same
"name": "string"every time, which hides bugs that only appear with varied input.
None of this is fatal. But it’s friction that compounds as the API grows. For a fuller look at where these gaps add up, see our Bruno alternative all-in-one API platform breakdown.
Generate a mock server from your OpenAPI spec instead
The cleaner path is to derive the mock from the contract you already maintain. Apidog does this: import or write an OpenAPI spec, and it generates a working mock server from the same definitions you use for design, testing, and docs. One source of truth, not three.

A few things make this different from bolt-on tooling:
- Smart mock from the spec. Apidog reads field names and types and returns plausible data, so an
emailfield looks like an email and acreated_atfield looks like a date, with no rules to write. - Dynamic responses. Responses generate from your schema on each request, so you get varied data instead of one frozen example. You can layer in conditional rules when you need a specific case.
- No-code setup. You don’t write or host a separate server. Define the endpoint in the spec and the mock URL is ready.
- Stays in sync. Update the spec and the mock updates with it, because they share one definition.
Because the mock, the request library, and the documentation come from the same project, there’s no third place to keep aligned. If your workflow is Git-centric, the spec stays diffable and reviewable too, which pairs well with a Git-native API workflow. For more on where mocking earns its keep, see API mocking use cases.
Quick how-to: from spec to mock URL
Here’s the short version of standing up a mock from an existing spec:
- Import your spec. Bring in your OpenAPI (or Swagger) file, or point Apidog at the spec URL. Existing endpoints and schemas come in as-is.
- Open an endpoint. Each imported endpoint already has its schema, so the mock has everything it needs.
- Grab the mock URL. Apidog exposes a local and a cloud mock endpoint automatically. No server to deploy.
- Send a request. Hit the mock URL and you get schema-shaped JSON back, generated from the spec.
- Tune responses (optional). Add rules for specific status codes or edge cases, like that
429, when you need to test a particular path.
You point your front-end, mobile build, or test suite at the mock URL and keep moving while the backend catches up.
When the workarounds are enough
To be fair, you don’t always need a spec-driven mock. Stick with Bruno plus a lightweight external tool when:
- You only need to stub one or two endpoints for a quick local test.
- Your team is happy maintaining Bruno’s file-based collections and doesn’t want to switch tools.
- A static stub is fine because you’re not testing varied data or many error paths.
- You already run Mockoon, WireMock, or Prism and the extra source of truth isn’t slowing you down.
The trade-off is real: the lightweight path keeps Bruno’s simplicity but leaves you maintaining mocks separately. The spec-driven path removes that drift at the cost of adopting a broader platform. Pick based on how much your API is growing.
FAQ
Does Bruno have a built-in mock server?
No. Bruno is an API client for sending requests and running tests. It has no native mock server, so to mock endpoints you use an external tool or write your own stub server and point Bruno at it.
What’s the easiest way to add mocking to a Bruno-style workflow?
Generate the mock from your OpenAPI spec instead of defining it separately. Tools like Apidog read the spec and produce a ready mock URL, so you keep one source of truth across design, mocking, testing, and docs rather than maintaining mock definitions in a second place.
Can I keep using Bruno and just add a mock server alongside it?
Yes. Run an external mock tool such as Mockoon, WireMock, or Prism, define responses there, and point Bruno at that URL. It works, but your spec, requests, and mock data live in separate places and can drift, which is the main reason teams consolidate.
If maintaining a separate mock layer has started to cost more than it saves, it’s worth trying a spec-driven mock. Import your OpenAPI file into Apidog and you’ll have a working mock URL in a few minutes, no extra server to host.



