MockHub documentation
Everything you need to run MockHub, mock REST and SOAP services, share them with your team, and run it in production test environments.
Quick start
docker run -p 8080:8080 -v mockhub-data:/data abhaypratap/mockhub
Open http://localhost:8080/__admin/mockhub/ui/. Go to Examples, install Petstore — REST basics, then call it:
curl http://localhost:8080/example-petstore/pets/42
{"id":"42","name":"Pet 42","status":"available"}Want to look around first? The live demo runs the examples. Sign in as demo / demo (read-only), and call the mocks directly:
curl https://mockhub.devops-monk.com/example-petstore/pets?status=sold
Concepts
| Term | Meaning |
|---|---|
| Project | The mocks of one service. It owns a base path such as /payment-service, so its mock URL is https://your-host/payment-service. |
| Stub | A rule: when a request matches, send this response. Stubs are plain WireMock stub mappings, edited relative to the project's base path. |
| Priority | When several stubs match, the lowest number wins (1 is highest, the default is 5). Use it for "specific case first, generic fallback last". |
| Scenario | A named state machine that lets the same request get different answers over time. |
Your first stub
Create a project, open it, and choose REST stub. Set the method and path, then the response status and body, and save. Click Send in the Try it panel to call it.
The form covers the common cases. Switch to JSON for anything else WireMock supports. This is the same stub as JSON, as sent through the API:
{
"name": "Get payment",
"request": { "method": "GET", "urlPathTemplate": "/payments/{id}" },
"response": {
"status": 200,
"headers": { "Content-Type": "application/json" },
"jsonBody": { "id": "{{request.path.id}}", "status": "PAID" },
"transformers": ["response-template"]
}
}Not sure where to start? The template gallery button in the stub list has ready-made patterns for common cases.
Request matching
| URL match | Example | Matches |
|---|---|---|
| Path equals | /pets | /pets, /pets?any=query |
| Path and query equal | /pets?status=sold | exactly that URL |
| Path template | /pets/{id} | /pets/7, and exposes request.path.id |
| Path matches regex | /pets/[0-9]+ | numeric ids only |
| Any URL | anything under the project's base path |
Add conditions on query parameters, headers, cookies and the body. Every condition must match. Body matchers include JSON equals (optionally ignoring extra fields and array order), JSONPath (for example $[?(@.amount > 1000)]), XML equals, XPath, contains and regex.
Templating
Turn on Response templating to build responses from the request:
| Helper | Gives |
|---|---|
{{request.path.id}} | a path-template variable |
{{request.query.page}} | a query parameter |
{{request.headers.X-Tenant}} | a header |
{{jsonPath request.body '$.email'}} | a value from a JSON body |
{{xPath request.body '//id/text()'}} | a value from an XML/SOAP body |
{{randomValue type='UUID'}} | a random UUID (also ALPHANUMERIC, NUMERIC…) |
{{randomInt lower=1 upper=100}} | a random number |
{{now offset='7 days' format='yyyy-MM-dd'}} | dates |
{{#if …}} {{#eq a 'b'}} {{#each …}} | conditionals and loops |
See the WireMock templating reference for the full list.
Scenarios
Give stubs the same scenario name. Each stub answers only in its required state and can move the scenario to a new state. Every scenario starts in Started. Reset or jump between states from the project's Scenarios tab. The Shopping cart example shows a complete flow.
Delays & faults
- Fixed: always wait N ms.
- Random range: uniform between two values.
- Realistic: log-normal latency around a median, with a long tail.
- Trickle: send the body in chunks over a period of time.
- Faults: connection reset, empty response, malformed chunk, or random data then close.
A global delay for every response is on the Server page.
SOAP & WSDL
Choose SOAP stub, or switch an existing stub's service type to SOAP. Enter the operation element (the first element inside soap:Body, such as GetCustomer) and MockHub matches it for you. Add XPath conditions to answer differently per field value:
{ "matchesXPath": { "expression": "//*[local-name()='customerId']/text()", "equalTo": "42" } }Import → WSDL creates, for the service's SOAP binding:
- one stub per operation, with request and response envelopes generated from the XSD (including enums, attributes and nested types)
GET <endpoint>?wsdl, serving the WSDL withsoap:addressrewritten to the mock- a low-priority SOAP fault for operations without a mock
Proxy & record
Set a stub's response to Proxy to forward matching requests to a real service. A low-priority "any URL" proxy stub lets you mock a few endpoints and pass everything else through. The project's base path is removed before forwarding.
Server → Record from a real service forwards traffic to a target and saves every answer as a stub in the project you choose.
Import
| Format | What you get |
|---|---|
| OpenAPI 3 / Swagger 2 (JSON or YAML) | One stub per operation. The response uses the spec's example, or sample data generated from the schema. Optionally strip a prefix such as /api/v1. |
| WSDL 1.1 | See SOAP & WSDL. |
| WireMock mappings | A {"mappings": [...]} file, an array, or one stub. Exports from another project are re-rooted automatically. |
Postman & Bruno
On a project's Import & export tab:
- Postman: a v2.1 collection grouped into folders, with a
baseUrlvariable and a status test per request. Import it from Postman's Import dialog. - Bruno: a zip containing a collection folder of
.brufiles and a MockHub environment. Unzip it and use Open Collection. - WireMock: plain mappings for any WireMock server.
Request bodies come from each stub's matchers, or from the Example request body you set in the editor. Change baseUrl to run the same collection against the real service.
Request log
The Requests tab updates live. Filter to Unmatched to find missing stubs. Click a request to see headers and bodies, the closest stubs and how near they came, and a button that creates a stub from that request.
Sign-in & roles
Sign-in is off until you set MOCKHUB_USERS. Mock endpoints are never protected; only the UI and the admin API are.
MOCKHUB_USERS="lead:s3cret:admin,qa:qa-pass:editor,dev:sha256:9f86d0…:viewer"
| Role | Can |
|---|---|
| viewer | read everything and download exports |
| editor | also create, edit and delete projects and stubs, import, record |
| admin | also global settings, restore, and reset or shutdown through the native API |
/__admin/*.Configuration
| Variable | Default | Purpose |
|---|---|---|
PORT | 8080 | Port for UI, API and mocks |
MOCKHUB_DATA_DIR | /data | Where projects and stubs are stored |
MOCKHUB_PUBLIC_URL | from the request | Public URL used in exports |
MOCKHUB_USERS | empty | Enables sign-in, see above |
MOCKHUB_JOURNAL_MAX_ENTRIES | 5000 | Requests kept in the log |
MOCKHUB_STUB_CORS | true | CORS headers on mock responses |
WIREMOCK_OPTIONS | empty | Any extra WireMock flag |
API & CI
Everything in the UI is available over HTTP at /__admin/mockhub/api. With sign-in on, send HTTP Basic credentials. The native WireMock API stays available at /__admin.
# create a project curl -X POST $HUB/__admin/mockhub/api/projects -d '{"name":"Orders","slug":"orders"}' # load stubs from your OpenAPI spec before the test run curl -X POST $HUB/__admin/mockhub/api/projects/$ID/import/openapi --data-binary @openapi.yaml # add one stub (paths are relative to the project) curl -X POST $HUB/__admin/mockhub/api/projects/$ID/stubs \ -d '{"request":{"method":"GET","url":"/health"},"response":{"status":200}}' # download the Postman collection curl -OJ $HUB/__admin/mockhub/api/projects/$ID/export/postman # check which calls your service made, and which didn't match curl "$HUB/__admin/mockhub/api/projects/$ID/requests?unmatched=true"
| Endpoint | Purpose |
|---|---|
GET|POST /projects | list, create |
GET|PUT|DELETE /projects/{id} | read, update, delete (with its stubs) |
GET|POST /projects/{id}/stubs | list, create |
GET|PUT|DELETE /projects/{id}/stubs/{stubId} | read, update, delete |
POST …/stubs/{stubId}/clone?target=, …/move?target= | copy or move a stub |
GET|DELETE /projects/{id}/requests | request log |
GET /projects/{id}/export/{postman|bruno|wiremock} | exports |
POST /projects/{id}/import/{openapi|wsdl|wiremock} | imports |
GET /examples, POST /examples/{id}/install | built-in examples |
GET /backup, POST /restore | everything as one file |
Deployment
Docker Compose
services: mockhub: image: abhaypratap/mockhub ports: ["8080:8080"] environment: MOCKHUB_PUBLIC_URL: https://mocks.acme.internal volumes: ["mockhub-data:/data"] volumes: mockhub-data:
AWS ECS with Terraform
The repository's deploy/terraform module creates a Fargate service, an encrypted EFS volume for /data, an Application Load Balancer with optional HTTPS, and the IAM and security groups around them.
cd deploy/terraform cp terraform.tfvars.example terraform.tfvars terraform init && terraform apply
Behind nginx on a VM
location / { proxy_pass http://127.0.0.1:8095; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 120s; }
Persistence & backup
Stubs live in /data/mappings as WireMock JSON files. Projects live in /data/mockhub/projects.json, and response files in /data/__files. Back up the volume, or use Server → Download backup for a single JSON file you can restore into any MockHub.
Limits
- Run one instance per data directory. WireMock keeps stubs in memory and reads the files only at startup.
- Scenario states and the request log are in memory and reset on restart.
- Project base paths can't collide with each other or with
/__admin.