Choose the smallest substitute that proves the behavior.

An API mock answers a request with a response you define. A stateful mock changes that response as the test moves through a scenario. A service clone implements selected provider behavior and keeps records that later requests can read or change. All three can keep test traffic away from a live customer service; they differ in what your team must model and what the test can observe.

For a tax label or feature flag, one response may be enough. For checkout, a useful test may need a customer, a payment, a callback, an order, and an entitlement to agree. Start by listing the request and state transitions your application actually depends on. Choose a substitute that can represent those transitions without pretending to cover the provider’s entire API.

APPLICATION

Vendor-shaped request

Your app calls the same API contract used in the integration.

base URL changes
ISOLATED SERVICE

State you can inspect

A clone or mock returns the behavior your scenario needs without shared live side effects.

known response
ASSERTION

Customer-visible result

Check the browser state and the callback or record that caused it.

contract + screen state
Test the boundary your app actually crossesKeep the vendor API request, isolate its state, and inspect the callback or response your application consumes.

Stateful mocks are real state machines.

WireMock’s scenario documentation models a sequence with an initial state, request matching, and a transition to a named next state. That is enough for many workflows and keeps the behavior close to the test’s intent. It also means your team owns the mappings, response bodies, state names, and reset discipline.

Code example
stubFor(post(urlEqualTo("/checkout"))
  .inScenario("checkout")
  .whenScenarioStateIs(Scenario.STARTED)
  .willReturn(okJson("{\"status\":\"processing\"}"))
  .willSetStateTo("completed"));

stubFor(get(urlEqualTo("/checkout/status"))
  .inScenario("checkout")
  .whenScenarioStateIs("completed")
  .willReturn(okJson("{\"status\":\"paid\"}")));

The Java DSL above is illustrative and assumes WireMock’s static imports. Reset scenarios between tests, and verify that the application is calling the mock endpoint you intended. A stale base URL can make a test pass against a real service or fail because only half the calls were intercepted.

Clones package provider behavior you can reuse.

A clone can reduce repeated fixture work when several tests need the same provider-shaped records and transitions. Molar Clones exposes only the operations and states documented for each service. Check the clone catalog against your application’s calls before relying on it. A Stripe clone covering a PaymentIntent does not imply coverage for every subscription, Connect, tax, or dispute path.

The practical tradeoff is control versus compatibility. A configurable mock gives you precise response control and can model an unusual failure quickly. A provider test environment checks more of the provider contract but may be slower or less controllable. A clone gives reusable supported behavior and inspectable records, but still needs compatibility checks against the provider.

Run the same checkout against each option.

  1. Create a disposable customer and start with no entitlement.
  2. Submit the payment request from the browser or application API.
  3. Read the created payment record with a later request.
  4. Deliver the callback or transition the scenario state.
  5. Assert that the application grants access once.
  6. Repeat the callback and confirm idempotency.
  7. Reset all state and confirm the next run starts clean.

Record which layer each assertion checks. A 200 response proves that one request succeeded; it does not prove that your order changed. A stateful substitute proves the model you configured or the behavior it implements; it does not prove that the real provider accepts every field or emits identical timing.

Make failure and compatibility checks explicit.

Choose one declined payment, one delayed callback, one malformed or missing object, and one signature failure that matters to your application. Compare status codes, required fields, error payloads, and callback ordering with the provider’s authorized test environment. Keep the compatibility test small enough to run when you update your integration or substitute.

Give each parallel run its own namespace, account, or process. Reset WireMock scenarios with its admin API or restart the instance according to your setup. For a clone, use the documented snapshot and restore path. Do not assume that “reset” cleared an external provider sandbox.

Choose from the calls your app actually makes.

Read Molar’s supported clone catalog, then map each required endpoint to a mock, clone, or provider test path. Keep the substitute close to versioned test code and review changes to mappings as carefully as application code. The WireMock comparison and Stripe testing guide show the tradeoff on concrete payment examples.

No substitute removes the need to test the provider contract. It gives you a safer, repeatable place to exercise your application’s own behavior before a smaller compatibility check reaches the provider sandbox.