Skip to content

mock

stable

Create in-memory HTTP mock servers for testing, with route matching, call count tracking, expectation verification, and recorded argument inspection.

use plugin mock::{create_request, create_response, MockServer.new, …}
14 functions Utilities
/ filter jk navigate Esc clear
Functions (14)
  1. create_request Build a request table with method, url, and body
  2. create_response Build a response table with status and body
  3. MockServer.new Create a new empty mock server
  4. add_route Register a route with a canned status, body, and headers
  5. match_request Find a matching route, return its response, increment its counter
  6. routes List all registered routes with their call counts
  7. clear Remove all routes from the server
  8. remove_route Remove a single route by method and path
  9. call_count Get how many times a route has been matched
  10. expect Set the expected call count for a route
  11. verify Return the list of unmet expectations (empty = all passed)
  12. reset_counts Reset all call counters without removing routes
  13. recorded_args Get the recorded arguments for every call to a route
  14. route_count Get the total number of registered routes

Overview

mock lets you stand up a lightweight, in-memory HTTP server entirely inside your test code — no sockets, no ports, no real network. The core concept is the MockServer class: a stateful handle that holds a list of routes, where each route maps a method and path to a canned status, body, and headers. As your code under test "sends" requests through match_request, the server records how many times each route was hit and what arguments came with each call.

The mental model is: create a server with MockServer.new, register the responses you expect with add_route, drive your code so it calls match_request, then assert on behaviour with call_count, recorded_args, or the expect/verify pair. Two free helpers, create_request and create_response, build plain request/response tables when you just need a data shape rather than a full server. Reach for mock whenever you are unit-testing code that talks to an HTTP API and want deterministic, inspectable responses.

Common patterns

Register routes, serve a request, and assert on the response:

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/users", 200, '{"users":[]}', #{})
server.add_route("POST", "/users", 201, '{"id":1}', #{})

let resp = server.match_request("GET", "/users")
print("status: {resp["status"]}")
print("body:   {resp["body"]}")

let missing = server.match_request("DELETE", "/users")
print(missing)

Set an expectation up front, exercise the code, then verify it was met:

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/health", 200, "ok", #{})
server.expect("GET", "/health", 2)

server.match_request("GET", "/health")
server.match_request("GET", "/health")

let failures = server.verify()
print("called {server.call_count("GET", "/health")} times")
print("expectation failures: {failures}")

Inspect what each call carried, then reset counters to reuse the server:

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("POST", "/login", 200, '{"token":"abc"}', #{})

server.match_request("POST", "/login", #{ "user": "ada" })
let calls = server.recorded_args("POST", "/login")
print("recorded calls: {calls}")

server.reset_counts()
print("after reset: {server.call_count("POST", "/login")}")

Build a request table with method, url, and body

Builds a plain table representing an HTTP request with method, url, and body fields. Useful for constructing test inputs by hand. The body argument is optional and defaults to an empty string when omitted.

use plugin mock::{create_request}

let req = create_request("GET", "/api/users", "")
print(req["method"])
print(req["url"])

It pairs with a server when you want to pass a prebuilt request shape around your own test helpers:

use plugin mock::{create_request, MockServer}

let server = MockServer.new()
server.add_route("POST", "/api/users", 201, '{"id":7}', #{})

let req = create_request("POST", "/api/users", '{"name":"Ada"}')
let resp = server.match_request(req["method"], "/api/users")
print(resp["status"])

Build a response table with status and body

Builds a plain table representing an HTTP response with status and body fields. Handy for asserting against expected response shapes.

use plugin mock::{create_response}

let resp = create_response(200, '{"ok": true}')
print(resp["status"])
print(resp["body"])

Create a new empty mock server

Creates a new, empty mock server with no routes registered. Returns a MockServer handle whose methods are called with dot syntax.

use plugin mock::{MockServer}

let server = MockServer.new()
print("routes so far: {server.route_count()}")

Register a route with a canned status, body, and headers

Registers a route on the server. When a later match_request matches the same method (case-insensitive) and path, this route's status, body, and headers are returned. Pass headers as a map literal of string keys to string values (use #{} for none).

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/users", 200, '{"users":[]}', #{})
server.add_route("POST", "/users", 201, '{"id":1}', #{ "Location": "/users/1" })
print("registered {server.route_count()} routes")

Find a matching route, return its response, increment its counter

Looks up a route by method and path. On a match it increments that route's call counter and returns a table with status, body, and headers. Returns nil when no route matches. An optional third map argument is also accepted: its string key/value pairs are stored as the recorded arguments for the call.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/ping", 200, "pong", #{})

let resp = server.match_request("GET", "/ping")
print(resp["body"])

let none = server.match_request("GET", "/missing")
print(none)

Capture per-call arguments by passing a map as the third argument:

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("POST", "/search", 200, "[]", #{})

server.match_request("POST", "/search", #{ "q": "zolo" })
print(server.recorded_args("POST", "/search"))

List all registered routes with their call counts

Returns a table of all registered routes. Each entry exposes method, path, status, body, and call_count, making it a quick way to snapshot the server's state.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/a", 200, "A", #{})
server.add_route("GET", "/b", 200, "B", #{})

server.match_request("GET", "/a")
let all = server.routes()
print("first route: {all[1]["path"]} called {all[1]["call_count"]}x")

Remove all routes from the server

Removes every route from the server, returning it to its freshly-created state.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/x", 200, "x", #{})
server.clear()
print("routes after clear: {server.route_count()}")

Remove a single route by method and path

Removes a single route matching the given method and path, leaving all other routes intact.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/keep", 200, "keep", #{})
server.add_route("GET", "/drop", 200, "drop", #{})

server.remove_route("GET", "/drop")
print("routes left: {server.route_count()}")

Get how many times a route has been matched

Returns how many times the given route has been matched by match_request. Returns 0 if the route does not exist or was never called.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/hit", 200, "ok", #{})

server.match_request("GET", "/hit")
server.match_request("GET", "/hit")
print("hits: {server.call_count("GET", "/hit")}")

Set the expected call count for a route

Sets the expected number of calls for an already-registered route, to be checked later with verify. Returns true on success. The route must exist or the call fails with an error.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/once", 200, "ok", #{})
server.expect("GET", "/once", 1)

server.match_request("GET", "/once")
print("expectations met: {server.verify()}")

Return the list of unmet expectations (empty = all passed)

Checks every route that has an expectation set via expect and returns a table of failures. Each failure entry contains method, path, expected, and actual. An empty table means all expectations passed.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/twice", 200, "ok", #{})
server.expect("GET", "/twice", 2)

server.match_request("GET", "/twice")
let failures = server.verify()
print("failures: {failures}")

Reset all call counters without removing routes

Resets every route's call counter and clears its recorded arguments, without removing any routes. Useful for reusing one server across multiple test cases.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/r", 200, "ok", #{})

server.match_request("GET", "/r")
server.reset_counts()
print("after reset: {server.call_count("GET", "/r")}")

Get the recorded arguments for every call to a route

Returns a table of the arguments recorded for each call to the route, in call order. Each entry is the map that was passed as the third argument to match_request. Returns nil if the route does not exist.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("POST", "/log", 200, "ok", #{})

server.match_request("POST", "/log", #{ "level": "info" })
server.match_request("POST", "/log", #{ "level": "warn" })
print(server.recorded_args("POST", "/log"))

Get the total number of registered routes

Returns the total number of routes currently registered on the server.

use plugin mock::{MockServer}

let server = MockServer.new()
server.add_route("GET", "/a", 200, "A", #{})
server.add_route("GET", "/b", 200, "B", #{})
print("total routes: {server.route_count()}")
enespt-br