Response Templating: Dynamic Stubs vs Reusing OpenAPI Examples

Response Templating: Dynamic Stubs vs Reusing OpenAPI Examples

Quick answer: Dynamic response templating is powerful precisely because it can echo parts of the request back into the response, which makes it easy to overfit tests to clever stub behavior. Before reaching for a template, check whether the OpenAPI example already expresses the response you need. Reuse the example for fixed, contract-shaped data and reserve templating for the few fields that genuinely depend on the request, such as an echoed ID or a generated timestamp. I reached for templating on almost every stub early on, and it came back to bite us. A stub built a response by concatenating values from the request, so the test passed against the mock. When the same client hit the real server, the response did not echo those values the way the template had, and the client broke. The mock was not modeling the contract; it was modeling whatever the test wanted to hear. Reining templating back and anchoring responses to OpenAPI examples made the mock behave like the real service instead of an accomplice. What response templating actually does A templating engine evaluates placeholders inside a stub at request time, so a single mapping can produce different responses from different inputs. It can read request parameters, headers, or the body, and insert them into the response. That is the right tool for genuinely dynamic values. An echoed ID is a legitimate use because the real API often returns the identifier the client supplied. The trouble starts when templates are used to manufacture ordinary data that the contract already defines, which lets the mock drift away from the real response shape. Templating versus OpenAPI examples The two solve different problems and should not be treated as interchangeable. The table below is the decision framework I use when writing a stub. Need Dynamic template OpenAPI example Fixed business data Can invent values not in the contract Pinned to the documented shape Echoed request ID Correct and necessary Cannot vary with the request Generated timestamp Appropriate, but format must match spec Static value would be misleading Contract fidelity Easy to overfit Stays aligned with the schema Drift risk Higher as logic accumulates Lower; example lives with the spec Anchor the response, then template the edges The robust pattern starts from the OpenAPI example as the base response and only overrides the fields that must be dynamic. That keeps every fixed field shaped by the contract and confines templating to a small, reviewable surface. Validating the generated response against the schema is the guard that catches a template producing a value of the wrong type or format, which is the most common way a clever stub drifts. Keep template logic small and obvious Once a stub contains branching, arithmetic, or string manipulation, it is effectively application code, and it needs the same discipline: keep it short, name the intent, and test it. Avoid embedding business rules in a template that also exist in the real service, because the two implementations will diverge. If a template is growing complex, it usually means the test should use a fixed example instead, or the scenario belongs in a dedicated contract test rather than a mock mapping. Match the real formats, not convenient ones Generated timestamps and numbers are the subtle traps. A template that emits a timestamp in a different format than the spec promises, or a number as a string, will train the client to parse the wrong thing. Pull the format from the schema and validate it. When the dynamic fields are constrained to the documented formats and the rest of the response comes from the example, the mock stays faithful and the test is far less likely to pass against behavior the real server does not provide. Avoid random values inside a template A template that generates random identifiers or amounts makes a test nondeterministic, and the failure becomes hard to reproduce. If a value needs to vary, derive it from a fixed seed or from the request itself rather than an unseeded generator, and keep the format constrained by the schema. Prefer echoing a stable, predictable value so two runs of the same test produce the same response. This is the same reproducibility rule that applies to test data generally: a dynamic field is fine when it is deterministic, but a random one quietly turns a reliable mock into a source of flaky failures. FAQ When should I use a template instead of an example? Only for fields that genuinely depend on the request, such as an echoed identifier or a generated timestamp. Use the OpenAPI example for fixed data so the response stays shaped by the contract rather than invented by the stub. Why did the mock pass but the real server fail? Over-templating let the mock echo values the client wanted rather than what the real API returns. Anchoring responses to the spec example and validating against the schema prevents the mock from overfitting the test. How do I keep generated timestamps safe? Generate them at runtime but force the format to match the schema, then validate the response. A template that emits the wrong format trains the client to parse a value the real server never sends. What if my template logic is getting complicated? Treat that as a warning. Move fixed data back to an example, or promote the scenario to a dedicated contract test. Mock templates should stay small and obvious rather than accumulate a second copy of business logic. This is part of the Powerduck vs WireMock hub — start there for the full comparison of spec-first and code-first mocking.

Original Source

Read the full article at Dev →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.