A team is building a customer support screen. The layout is ready, but the customer API is still being developed. The screen needs to display account details, handle missing records, and let an agent retry a failed lookup. Waiting for the backend would delay all of that work, even though much of it depends on decisions the teams could make now.
A mock server gives the application an HTTP endpoint that returns controlled responses. The client can send requests through its normal API code while the provider is being built. This creates useful independence, provided everyone understands which parts of the interaction have been agreed and which remain assumptions.
Agree on the Interaction First
For the support screen, the teams might agree that GET /api/customers/42 returns a 200 response with a JSON body:
{
"id": 42,
"name": "Maya Chen",
"status": "active"
}
That example answers only part of the design question. Can name be missing? Which account statuses exist? What happens when the customer cannot be found, and how is that different from the agent lacking permission to view the record? The screen needs those answers to behave coherently.
An OpenAPI description can record paths, parameters, schemas, security requirements, and possible responses in a format that tools can use. Examples make the agreement easier to discuss, while schemas describe constraints beyond one sample. Neither establishes that an implementation conforms to the description; that still needs verification.
For this screen, the team should record unresolved choices alongside the agreed behaviour. A temporary assumption about an optional name is manageable when it is visible. It becomes harder to correct once several screens silently depend on it.
Match the Request the Client Should Make
A mock that returns the customer record for every incoming request can hide an incorrect path, a missing query parameter, or the wrong HTTP method. The page looks complete even though its API client would fail against the intended service.
Configure the mock to recognise the parts of the request that matter to the interaction. Unexpected requests should produce a visible failure, and tests should check which calls were actually made. Avoid requiring incidental details, such as header order, that the real API does not depend on.
MockServer's expectations pair request matchers with actions such as responses and delays. This gives a test control over what a dependency does when a particular request arrives. It is useful for exercising the client's HTTP behaviour without implementing the provider's database or business logic.
The important boundary is the one being tested. Replacing the network call with a function that returns an object can be appropriate for a component test, but it does not exercise the same path as an application making an HTTP request to a mock server.
Build Scenarios Around User Decisions
One complete customer record is enough to begin laying out the screen. It is insufficient for deciding how the screen behaves during ordinary uncertainty. A support agent needs to know whether to correct a search, request access, wait, or try again.
A useful initial set of scenarios might look like this:
| Scenario | Simulated response | Behaviour to examine |
|---|---|---|
| Known customer | 200 with the agreed fields | The screen presents the correct account. |
| Missing customer | 404 with the agreed error body | The agent can revise the lookup without losing context. |
| Access denied | 403 for an authenticated agent without permission | The screen explains the access limitation. |
| Incomplete profile | 200 with an optional field omitted | Missing information has a deliberate presentation. |
| Slow lookup | A response delayed by a fixed interval | Loading, cancellation, and repeated actions behave sensibly. |
| Unavailable service | 503 with the agreed error format | The screen preserves useful work and offers appropriate recovery. |
These responses are examples for this proposed API. The provider and consumer still need to agree on their exact meaning. A malformed response can also be valuable as a robustness test, but label it as an intentionally invalid case so it does not become mistaken for documented behaviour.
Make Timing Reproducible
A local mock usually responds quickly enough to conceal awkward transitions. Deliberate delays let the team inspect what happens while a request is pending, including whether a second click submits duplicate work or a loading indicator leaves the rest of the screen usable.
For the customer lookup, try two searches in succession and delay the first response until after the second arrives. The screen should continue showing the second customer. This reveals whether an old response can overwrite newer state, a problem that a single successful lookup will never exercise.
Use fixed delays and named scenarios when reproducing a failure. Random timing can help exploration, but an automated test needs a way to replay the conditions that caused it to fail. A delay tests the client's reaction to waiting; it does not measure the real provider's performance or establish a service-level guarantee.
Keep State Small and Isolated
Some interactions need more than static responses. After an agent updates a customer's display name, a subsequent lookup may need to return the changed value. A small amount of simulated state can support that workflow without recreating the entire backend.
That state needs a lifecycle. Each test should start from known data, and parallel tests should not overwrite each other's customers. Use an isolated mock instance or separate data scope, then reset it deliberately. A test that passes only after another test has prepared the mock is difficult to trust and diagnose.
A small custom service can be reasonable when the interaction needs specialised behaviour. Its cost grows with every rule copied from the provider. Keep the simulation focused on the decisions the client must make; the provider's own tests should establish whether its business rules are implemented correctly.
Choose a Tool That Fits the Work
If the team already discusses requests and examples in Postman, its mock server workflow can turn saved examples into responses served from a mock URL. Review the matching settings so the selected example represents the request being tested.
For automated tests that need programmable matching and controlled failure conditions, MockServer is another option. A custom HTTP application gives more freedom where the scenario cannot be expressed conveniently in the team's existing tooling. The useful comparison is how easily the team can define, review, reset, and run the required cases.
Whichever approach is used, keep mock configuration explicit and use synthetic customer data. The same client code should be able to target the intended environment through configuration, with a clear separation between development fixtures and live service access.
Close the Gap When the Provider Arrives
A client and its mock can agree perfectly while sharing the same incorrect assumption. This is why contract testing and integration testing remain necessary parts of the discussion. Provider verification can check recorded expectations against the implementation, while integration checks exercise the real connection and the configuration involved.
Start those checks as soon as a useful slice of the provider is available. Confirm request handling, response parsing, authentication, and browser access where relevant. A mock on the application's own origin will not reveal every cross-origin or cookie configuration problem in the deployed arrangement.
Keep the failure scenarios after integration. They remain useful for exercising conditions that are difficult to trigger safely in a shared environment, including timeouts and circuit breaker recovery. The confidence they provide depends on keeping the simulated behaviour under review as the API changes.
The support team should eventually receive a screen whose behaviour has been considered before every backend component was ready. The mock enables that progress by making the proposed interaction available early. Its job is complete only when the assumptions it helped develop have been checked against the service people will actually use.