Skip to content
routebase
API Mocking10 chapters

Chapter 07 of 10

Keeping Mocks in Sync With the Spec

A mock behind the contract is worse than no mock. The three states a generated rule can be in, why a published version should freeze rather than follow, and what regeneration overwrites.

A mock that has fallen behind the contract is not neutral. It is confidently wrong, and every consumer built against it is being taught a shape that no longer exists.

That makes synchronisation the property that decides whether a mock stays useful after week two. It is also the property most setups have no answer for, because the mock was generated once and then quietly became a copy.

Three states, and only one of them is stable

A rule that came from a specification can be in one of three relationships with it, and confusion here is the source of most mock surprises.

The three states a generated rule can be in. Following means the body is produced from the current schema on every request, so it cannot fall behind. Pinned means the rule is deliberately frozen against a published version and the tooling reports when the contract moves. Detached means somebody edited the body, which is a choice rather than an accident and stays in force until the rule is regenerated.

Following. The body is projected from the current schema each time the rule answers, so a field added this morning is in the response this afternoon. Nothing is stored, which means nothing can be stale.

Pinned. The rule is attached to a published version and answers that shape on purpose. This is the correct state for anything a consumer outside the team relies on, because a published version that changes underneath somebody is not a version at all.

Detached. Somebody edited the body by hand. The rule now belongs to them, and no schema change will touch it again until it is regenerated.

The state that causes trouble is a fourth one, which is a rule that was generated once by a tool with no concept of any of this. It looks derived, it is actually detached, and nothing will ever tell you which.

Why following is not always the goal

The instinct is to make everything follow, and it is the wrong instinct for anything published.

While a contract is still a draft, following is exactly right. The mock moves with the design, the frontend sees each change on its next request, and nobody has to remember to regenerate. That is the state a design-first workflow wants for the whole of the design phase.

Once a version is published, consumers depend on it. A mock that silently adopts the newest shape stops representing what those consumers actually receive, which makes it useless for reproducing their problems. Freezing it is the correct behaviour, and the thing you want from the tooling then is not synchronisation but detection.

The neighbouring decision, which is how a contract gets a new version at all, is covered in the versioning guide.

What a detection should tell you

A banner saying that something has changed is not much better than silence, because the next question is always which part.

A useful report names the version the rule is frozen at and the version the specification has reached, then lists what actually differs between them. A field added is a different problem from a field removed, and a type change is a different problem again. Without that breakdown, pulling the mock forward is an act of faith.

The second half is what happens when you accept. Regeneration rebuilds the body from the newer schema, which means any manual edits in that body are gone. Seeing the current body next to the proposed one before applying is the difference between an update and a loss.

Keeping the loop small

Two habits keep the drift from accumulating in the first place.

Re-run generation when the contract grows rather than when something breaks. A new endpoint arrives without a rule and returns a 404 that looks like a caller mistake, which is a slow and annoying way to find out that the specification moved.

Treat a manual edit as a decision rather than a shortcut. When a generated body is nearly right, changing the schema is almost always better than changing the body, because the schema change also reaches the documentation, the tests and everyone else reading the contract.

In Routebase

The state of a rule is visible in the tree rather than something you have to infer. Each row carries a colour for active, inactive, following the draft and out of sync with its source.

A rule generated from a draft version is in the following state. Its body editor is read-only, because the stored value is only the last snapshot and the response is projected from the current draft on every request. Customize takes ownership and stops the live updates, which is the deliberate move into the detached state.

A rule pinned to a published version gets drift detection instead. When the specification's latest published version moves past the one the rule is frozen at, a banner says so and names both versions.

A mock rule for GET /orders/{orderId} with a warning banner headed Out of sync with the spec, reading that the mock is frozen at v2.0.0 while the spec's latest published version is v2.1.0, next to a Review Changes button and a Sync from Spec button.
The banner states which version the rule is frozen at and which one the contract has reached, so the rule is not silently stale and not silently updated either.

Review Changes lists what differs between the two versions with the old and the new value beside each other, and Sync from Spec re-points the rule and regenerates its body. Re-Generate with Smart Mock does the same on demand from the rule menu, and both show the current body beside the proposed one before anything is applied. The Mock Server guide covers the three states and the diff.

Frequently asked questions

How do you keep a mock server in sync with an OpenAPI specification?

Keep the rule derived from the document rather than copied out of it, so the response is produced from the current schema instead of from a snapshot somebody pasted. Where the contract has been published and must not move, the rule should freeze against that version and report the difference when the specification moves on. Silent synchronisation and silent staleness are both worse than a visible diff.

What happens to a mock when the API specification changes?

It depends on what the rule is attached to. A rule following a draft picks the change up on the next request, because the body is projected from the schema rather than stored. A rule pinned to a published version keeps answering the old shape on purpose, and the only correct behaviour then is to flag that the contract has moved.

Should a mock follow the draft or a published version?

Follow the draft while you are designing, because that is when you want the mock to move with every change. Pin to a published version once somebody outside the team depends on it, since a version that shifts underneath a consumer is not a version. Most projects need both at once, which is why the choice belongs on the rule rather than on the server.

Does regenerating a mock rule overwrite manual changes?

Yes, and it has to. Regeneration rebuilds the body from the schema, so anything typed into that body by hand is replaced. The useful arrangement is that a manual edit takes the rule out of the derived state deliberately, and pulling it back in is a step somebody takes with a before-and-after comparison in front of them.

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.