OpenAPI-first mock server with deterministic scenario overrides and strict validation. Also supports proxy mode to intercept real backends.
npm i -D @brentbroeckx/mock-hubRun without installing:
npx mock-hub run --spec ./openapi.yaml --source ./scenariosGlobal install:
npm i -g @brentbroeckx/mock-hub
mock-hub run --spec ./openapi.yaml --source ./scenarios- Create an OpenAPI spec (example: openapi.yaml).
- (optional) Create a scenarios directory (example: scenarios).
- Run the server:
npx mock-hub run --spec ./openapi.yaml
or
npx mock-hub run --spec ./openapi.yaml --source ./scenarios
# Proxy mode (spec optional)
npx mock-hub run --proxy http://localhost:8080 --source ./scenariosmock-hub run [--spec <path>] [--proxy <baseUrl>] [--source <dir>] [--scenario <name>] [--ui] [--logging] [--port <number>] [--verbose]Help:
mock-hub run --help--spec <path>: Path to OpenAPI spec (YAML or JSON). Required unless--proxyis used.--proxy <baseUrl>: Enable proxy mode. For unmatched requests, forward to the real backend. Spec is optional in proxy mode.--source <dir>: Directory containing.yamlscenario files. Optional; if omitted, happy-path responses are used.--scenario <name>: Default scenario name to apply when no header override is provided.--ui: Launch interactive scenario selector (Ink).--logging: Enable deterministic logs (pretty in CLI/UI, JSONL in CI).--port <number>: Port to run the mock server (default: 4010).
npx mock-hub run --spec ./openapi.yaml
npx mock-hub run --spec ./openapi.yaml --source ./scenarios
npx mock-hub run --spec ./openapi.yaml --source ./scenarios --scenario PartnerDown
npx mock-hub run --spec ./openapi.yaml --source ./scenarios --ui
npx mock-hub run --spec ./openapi.yaml --source ./scenarios --logging
npx mock-hub run --proxy http://localhost:8080 --source ./scenarios
npx mock-hub run --proxy http://localhost:8080 --source ./scenarios --scenario RateLimitedUse the mock server in CI to make integration points deterministic, fast, and isolated from external system availability.
- Start the mock server on a known port with a fixed scenario and deterministic logging.
- Run your test suite against
http://localhost:<port>. - Let the pipeline cleanly shut down the server after tests complete.
CI=1 npx mock-hub run --spec ./openapi.yaml --source ./scenarios --scenario PartnerDown --port 4010 --logging
BASE_URL=http://localhost:4010 npm test
# Force a single request via header (override for one call in your tests)
curl -s -H "X-MockHub-Scenario: PartnerDown" http://localhost:4010/contracts >/dev/nullCI=1 npx mock-hub run --spec ./openapi.yaml --source ./scenarios --scenario HappyPath --port 4010 --logging
BASE_URL=http://localhost:4010 npx playwright testCI=1 npx mock-hub run --spec ./openapi.yaml --source ./scenarios --scenario PartnerDown --port 4010 --logging
# Validate 503 handling
curl -i -H "X-MockHub-Scenario: PartnerDown" http://localhost:4010/contracts
# Validate 500 handling using another scenario
curl -i -H "X-MockHub-Scenario: PaymentFailed" http://localhost:4010/payments- Same input
$\rightarrow$ same output. - No random behavior or time‑dependent responses.
- Safe to run in parallel CI jobs when using unique ports per job.
- UI mode (
--ui): requires interactive terminals and is non‑deterministic for automation. - Interactive scenario switching: can introduce state drift across parallel jobs.
Proxy mode lets Mock Hub act as a selective interception proxy. By default, requests are forwarded to the real backend. Scenario rules can override or transform responses without changing your client code. Use this to validate error handling, latency, or headers while still hitting the real service.
Resolution order in proxy mode:
- Scenario match → scenario logic applies
- No match → forward to
--proxy <baseUrl>
Notes:
- If a scenario rule defines
bodyorbodyFile, the response is fully mocked (no proxy). - If a rule defines only overrides (status/headers/delay/timeout), the response is proxied and then transformed. The body of the original request is kept when present.
- Happy-path OpenAPI mocks are disabled in proxy mode.
Proxy examples are available in scenarios/examples/proxy/scenarios.
Save as scenarios/examples/default/scenarios/partner-down.yaml:
scenario: PartnerDown
version: 1.0.0
description: Simulate partner API being unavailable
rules:
- id: partner-down-get
match:
path: /contracts/*
method: GET
headers:
X-User-Type: premium
respond:
status: 503
bodyFile: responses/partner_down.json
delayMs: 500
headers:
Retry-After: "30"
- id: dryrun-validation
match:
path: /contracts
method: POST
query:
dryRun: "true"
respond:
status: 400
body:
error: "Dry-run validation failed"
code: "VALIDATION_ERROR"For more examples take a look at: Mock-hub Scenario examples:
Per-request override using X-MockHub-Scenario:
X-MockHub-Scenario: PartnerDown
- OpenAPI spec:
--spec <path>(YAML or JSON). - Scenarios directory:
--source <dir>containing.yamlfiles and optionalresponses/files.
Templating is supported only inside respond.body and respond.bodyFile (including nested objects/arrays) for scenario-defined responses. Templates are string-only and resolved per response generation.
{{uuid}}RFC 4122 v4 UUID (new value per response){{now}}ISO-8601 timestamp (evaluated at response time){{increment}}In-memory counter (increments per response, resets on process restart)
No arguments, no nesting, no conditionals, no loops.
Use \\{{...}} to output a literal {{...}}.
respond:
status: 201
body:
id: "{{uuid}}"
createdAt: "{{now}}"
sequence: "{{increment}}"
note: "Literal: \\{{not-a-template}}"Scenario:
respond:
status: 201
bodyFile: responses/templated_body.jsonResponse file (templates allowed inside JSON string values):
{
"id": "{{uuid}}",
"createdAt": "{{now}}",
"sequence": "{{increment}}"
}- Templates are only allowed in
respond.bodyandrespond.bodyFilestring values (including nested objects/arrays). - Templates are not allowed in status codes, headers, match rules, delays/timeouts, or paths/methods.
- Unknown helpers, arguments, nesting, malformed syntax, or templates in non-string values fail validation before startup.
Validation happens before any scenario execution. Invalid files fail fast with precise errors.
- Syntax errors are rejected with file and line/column.
- Duplicate keys are rejected.
- Only known root keys are allowed.
- No additional properties allowed.
- Required fields must exist.
- Arrays like
rulesmust be non-empty. - Rule
idvalues must be unique within a file.
- HTTP status must be
$100$ –$599$. - HTTP method must be valid (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD).
-
pathmust start with/and may include at most one*wildcard. -
bodyandbodyFileare mutually exclusive. -
delayMs/timeoutmust be non-negative. -
versionmust matchx.y.z.
- Scenario names must be unique.
- Reserved scenario names (prefix
auto-gen-) are rejected.
ERROR scenarios/auth.yaml:12:4
○ payment-failure: rules[0].match.method
→ "FETCH" is not a valid HTTP method
.
├── src
│ ├── cli
│ ├── openapi
│ ├── responses
│ ├── rules
│ ├── scenarios
│ ├── server
│ ├── state
│ ├── ui
│ └── ...
├── dist
├── scenarios
└── openapi.yaml
