Skip to content
routebase
API Mocking10 chapters

Chapter 02 of 10

Which Rule Answers a Mock Request

A mock server is a router before it is anything else. What can be matched, why several rules routinely overlap, how priority breaks the tie, and what should happen when nothing matches.

Before a mock server is a source of data it is a router. Something has to take an incoming request and decide which of your configured answers it gets, and that decision is where most confusing mock behaviour comes from.

The four things a request can be matched on

Matching runs from coarse to fine, and each level exists because the level above it was not selective enough.

The method. A route with a GET and a POST is two rules, not one. A wildcard that accepts any method is useful for a catch-all and misleading anywhere else, because it will happily answer a DELETE with a list.

The path pattern. Parameters stay as placeholders, so /orders/{orderId} answers for every id. This is the level most mocks stop at, and it is why they can only ever give one answer per route.

The query string. Matching on query parameters separates ?status=open from ?status=archived, and a wildcard on the value matches any limit while still requiring the parameter to be there.

The headers. This is the level that makes a mock resemble an API rather than a file server. A rule that requires an Authorization header and a rule that does not are the difference between a client that handles 401 and one that has never seen it.

Overlap is normal, not a mistake

Once you are matching on more than a path, several rules will qualify for the same request, and that is the intended state rather than a misconfiguration.

The common case is exactly the authenticated one, and it looks like this. One rule answers /orders with a list, a second answers /orders with a 401 when the token is missing, and a request carrying a valid token satisfies the first but not the second. A request without one satisfies only the second.

The other common case is a fixed path sitting under a parameterised one. A rule for /orders/summary and a rule for /orders/{orderId} both accept the same request, because summary is a perfectly good value for an id, and nothing about the patterns says which of them was meant.

Priority is the tiebreak, and it is a decision

When two rules qualify, something has to choose, and the only maintainable answer is an explicit order you control.

The rule of thumb is that the more specific rule wins. A rule with a header condition beats the same path without one, and a literal path segment beats a parameter in the same position. That ordering is not automatic in most tools, which means putting it in place is part of setting the mock up rather than something that happens to you.

The practical consequence is worth stating plainly, because it saves a great deal of time. If a mock answers with the wrong body and that body is itself correct, the problem is nearly always the order rather than the rule. Checking which rule actually matched is faster than reading either body.

What should happen when nothing matches

An unmatched request is the one case where the default behaviour is actively unhelpful.

A 404 is correct and uninformative, because it covers two very different situations. Either the path is not in your contract at all, which is a caller mistake, or it is in the contract and no rule was generated for it, which is your gap. The caller sees the same response in both cases and reasonably assumes the first.

Two things fix that asymmetry. A request log turns the ambiguity into a fact, because an unmatched request appears there with no rule attached. Proxy mode removes the question entirely by forwarding anything unmatched to a real backend, which when not to mock covers as the middle path between a mock and the real service.

In Routebase

A rule matches on its method and path pattern, and Advanced Matching adds the query and header conditions underneath.

A mock rule editor showing the method, path and status code in the header, a static JSON response body for an order list, and an Advanced Matching section with a query parameter pattern and a headers pattern written as JSON with asterisks as wildcards.
Query parameters and headers are matched as JSON patterns with an asterisk standing for any value, so one rule can require that a token is present without caring which token it is.

Both patterns are JSON objects where * matches any value, so {"Authorization": "Bearer *"} requires a credential without pinning it to one. Rules carry a priority that you set by ordering them in the tree, either by dragging or from the rule menu. Moves are scoped to the path folder, so reordering two /orders rules never disturbs the /users rules between them.

The tree colours each rule by state, so an inactive rule and one that has drifted from its source specification are visible without opening either. When something answers unexpectedly, the request log names the rule that matched, which turns a guess into a lookup. The Mock Server guide covers matching, priority and the rule tree.

Frequently asked questions

How does a mock server decide which response to return?

It walks its rules, keeps the ones whose conditions the request satisfies, and picks a winner among them. Method and path do most of the filtering, while query parameters and headers narrow it further where two rules would otherwise be identical. When more than one rule still qualifies, an explicit priority decides, which is why the order of your rules is configuration rather than an accident.

Can a mock server match on request headers?

A useful one can, because that is how you get two different answers from one route. Matching on an Authorization header lets the same path return data when a token is present and a 401 when it is not. That is the case every client has to handle and almost no mock offers. The same mechanism covers content negotiation, API version headers and feature flags.

What happens when no mock rule matches a request?

The mock returns a 404, and that response is genuinely ambiguous. It means either that the path does not exist in your contract or that nobody generated a rule for it, and the caller cannot tell those apart from the outside. The log is what separates them, and proxy mode is what removes the question by forwarding unmatched requests to a real backend.

How do you mock an authenticated endpoint?

Add two rules on the same path. One matches when the credential header is present and returns the data, the other matches the same path without that condition and returns the 401 your contract documents. Give the specific rule the higher priority, and the client that forgets its token gets the response it would get in production rather than a cheerful 200.

Last reviewed by The Routebase Team.

Ready to ship on it?

Routebase is live. Design your API once — docs, mocks, tests, and monitoring all follow from the same source.

14-day Pro trial — no credit card required.