Mocks++
This release builds on Resterm’s HTTP mock server with call verification, independent response sequences, better header matching, and new controls in both the CLI and TUI.
Mocking is still focused on HTTP. Native gRPC and GraphQL aware mocking remain planned for future releases. Check out _examples/mocks.http.
Match headers with rules
Header matching now supports exact, prefix, present, and absent rules:
### Authorized webhook
# @mock method=POST path=/webhooks/payment
# @match headers={"Authorization":{"prefix":"Bearer "},"X-Correlation-ID":{"present":true},"X-Debug":{"absent":true}}
HTTP/1.1 204 No ContentThe existing string and array forms remain shorthand for exact matching. For example, headers={"X-Tenant":"acme"} still requires that exact value.
Use {"prefix":"Bearer "} when only the start of a value is stable. Use {"present":true} when the header must exist and {"absent":true} when it must not.
Query matching and recursive JSON subset matching continue to work as before.
Inspect mock traffic from RestermScript
When the TUI owns the workspace mock server, request expressions and assertions can inspect its journal:
### Deliver webhook
# @name deliver-webhook
# @assert mock.received({
# method: "POST",
# path: "/webhooks/payment",
# headers: {Authorization: {prefix: "Bearer "}},
# json: {status: "completed"}
# })
POST http://127.0.0.1:8080/webhooks/payment
Authorization: Bearer demo-token
Content-Type: application/json
{"status":"completed"}mock.received(pattern) reports whether at least one request matched. mock.count(pattern) returns the exact number of matches.
Patterns can contain method, path, query, headers, and json. They use the same matching rules as @expect.
The mock object is available during TUI request evaluation. Its helpers return an error while the workspace mock server is stopped. A local value named mock, such as an @for-each loop variable, takes precedence.
For now, resterm run does not connect scripts to an external mock server. Use resterm mock verify for headless runs and CI.
Check that the expected calls arrived
Add @expect to a mock when it should receive an exact number of matching requests:
### Payment webhook
# @mock method=POST path=/webhooks/payment
# @match headers={"Authorization":{"prefix":"Bearer "}} json={"status":"completed"}
# @expect calls=1
HTTP/1.1 204 No ContentStart the server:
resterm mock ./api.httpRun the application or test that calls it, then check the result:
resterm mock verify ./api.httpA passing expectation is reported as:
PASS api.http:4 Payment webhook: 1 call(s)
A mismatch shows the expected and actual counts, then exits with status 1. This makes resterm mock verify suitable for CI as well as local testing.
Use calls=0 for routes that must not be called:
### Retired endpoint
# @mock method=GET path=/v1/legacy
# @expect calls=0
HTTP/1.1 410 Gone
Content-Type: application/json
{"error":"use /v2 instead"}Each expectation inherits the mock’s method, path, query matchers, header rules, and JSON body matcher. It checks received traffic rather than the response that was selected. Overlapping expectations can therefore count the same request independently.
Verification can load one file:
resterm mock verify ./api.httpIt can also scan a workspace recursively:
resterm mock verify --recursive ./requestsKeep sequence state separate between callers
Sequences still share one cursor by default. Add sequence-key when each resource, session, or caller should advance independently:
### Poll payment
# @mock method=GET path=/payments/{id} sequence=polling sequence-key=path.id
HTTP/1.1 503 Service Unavailable
Retry-After: 1
Content-Type: application/json
{"id": {{json.path.id}}, "status": "pending"}
---
HTTP/1.1 200 OK
Content-Type: application/json
{"id": {{json.path.id}}, "status": "completed"}The first call to /payments/pay_1 returns 503. A first call to /payments/pay_2 also returns 503. Calling either payment again advances only that payment to 200.
Sequence keys can come from four places:
sequence-key=path.idsequence-key=query.jobsequence-key=header.X-Correlation-IDsequence-key=cookie.session
Resterm uses the first value when a query parameter or header appears more than once. A missing or empty key returns 400 without advancing the sequence.
X-Resterm-Mock-Status still pins a response without advancing its cursor.
Reset every sequence:
resterm mock resetReset every route using one sequence name:
resterm mock reset pollingThe TUI provides the same operations through :mock reset and :mock reset polling.
Control a running mock server
The standalone server now supports three operational commands:
resterm mock reset [sequence]resets sequence cursors.resterm mock clearclears the request journal and access logs.resterm mock verify [file|dir]checks the current journal against@expectdeclarations.
These commands connect to http://127.0.0.1:8080 by default. Use --url for another address. HTTPS control calls also support --insecure when using a local development certificate.
The control channel accepts only local non-browser clients and never returns raw journal entries.
If a source file or directory is named reset, clear, or verify, pass it as an explicit path such as ./verify.
New TUI controls
The TUI now includes:
:mock verifyto check active expectations and open a pass or fail summary.:mock reset [sequence]to restart response sequences.:mock clearto clear the journal and access logs.- A separate
[status_bar.mock]theme entry for the mock server segment. - Warning colours on the mock segment when a reload fails.
gandGnavigation in scrollable help, history, request detail, log, and verification views.
Reserved control paths
The literal /.resterm/ namespace is now reserved for Resterm’s control endpoints. Mock routes inside it are rejected.