Creating Mocks

Proxying and Hosts

Most of the time you do not want to mock a whole API, just the parts that matter for the scenario at hand. This page shows how Mocko sits in front of real backends: forwarding unmatched requests, proxying conditionally from inside a template, and routing multiple services through one instance with hosts.

Forward what you do not mock

Start Mocko with a proxy URL and point your app at Mocko instead of the real API:

$mocko -u https://demo-api.mockoapp.net mocks

Requests that match a mock are answered by the mock. Everything else is forwarded to https://demo-api.mockoapp.net(a demo backend you can actually hit) with the same method, path, query string, headers, and body, and the backend's response comes back untouched. Your app cannot tell the difference; it just sees an API where one or two routes happen to be under your control.

Proxying from inside a template

The proxy helper moves that decision into the body, so a single route can be partly real and partly mocked:

mock "GET /posts" {
body = <<-EOF
{{#is request.query.userId 1}}
[]
{{else}}
{{proxy}}
{{/is}}
EOF
}

User 1 gets an empty list, everyone else gets the real backend. This is the single most useful pattern for testing edge cases against live systems, and the Mock One Edge Case recipe explores variations of it.

{{proxy}} halts template execution: the proxied response becomes the entire response, and anything after the helper in the template is ignored.

proxy also accepts a destination, used as a base URL with the request path appended. GET /users/42 through {{proxy 'http://other:3000'}} becomes GET http://other:3000/users/42. That lets different branches of one template proxy to different backends.

Hosts: several services, one Mocko

A host block gives a name to an upstream service and matches incoming requests by their Host header. This is how one Mocko instance stands in for several microservices at once:

host "billing" {
name = "Billing Service"
source = "billing.local"
destination = "https://demo-billing.mockoapp.net"
}

mock "GET /invoices/{id}" {
host = "billing"
format = "json"
body = <<-EOF
{ "id": {{request.params.id}}, "status": "past_due" }
EOF
}
  • source is the hostname to match on incoming requests.
  • destination is optional. When set, requests for this host that no mock matches are proxied there automatically, so each host gets its own passthrough backend.
  • A mock with host = "billing"only answers requests carrying that host's Host header. Mocks without a host field answer any host.
$curl -H 'Host: billing.local' http://localhost:8080/invoices/7
{ "id": 7, "status": "past_due" }

In real setups the Host header comes from DNS or service discovery rather than a curl flag: point billing.local at Mocko and the routing is automatic. The Mock Microservices by Host recipe walks through a complete two-service setup.

Templates can proxy to a named host by its slug, which keeps destination URLs out of mock bodies:

mock "GET /passthrough" {
body = "{{proxy 'billing'}}"
}

Hosts in the UI

Hosts can also be created and edited in the control panel, alongside mocks. Hosts defined in files are read-only there, and hosts created in the UI follow the same persistence rules as deployed mocks: in-memory by default, durable with Redis.

Behavior details

  • Proxied requests time out after 30 seconds by default. Tune it with -t on the CLI or the equivalent configuration on deployed instances.
  • A mock's delay applies before proxying too, so delay = 3000 plus {{proxy}} simulates a slow but otherwise real backend.
  • Proxied requests carry x-forwarded-* headers, and the original Host header passes through.
  • Without a proxy URL, a host destination, or a {{proxy}} call, unmatched requests return 404, as covered in How Matching Works.

Next

One piece of the mock file format remains: shared fixtures. Continue to Data Blocks.