Skip to content

Server

A running mock HTTP server, bound to a random local port.

Inherits from: Func

Constructor

Server() -> Server overload 1 of 2

Starts a server.

Server func -> R overload 2 of 2

Starts a server and calls func with it. The server is shut down when func returns.

Parameters

NameTypeDescription
func ((Server) -> R) Called with the Server.

Example

http.mock.Server do |server|
  echo $server.url

Fields

address @ Str [get]

The bound socket address, such as 127.0.0.1:41823.

url @ url.Url [get]

The server's base URL. Use / to build request paths.

Example
http.mock.Server do |server|
  http.get (server.url / "/users/42")

Methods

close()

Shuts the server down. Requests to its address then fail.

mock ...items -> Mock overload 1 of 2

Registers one or more mocks.

Each item is a dict pairing a request matcher with the response to return when it matches.

Parameters

NameTypeDescription
...items Dict[{respond: Value, ...}] Mock items, as described above.

Matching

Key Type Matches
method Str The HTTP method, case-insensitively
path Str The request path exactly
path_regex Str The request path against a regex
headers Dict Header name/value pairs that must all be present and equal
query Dict Query parameter name/value pairs that must all be equal
body_json A JSON value the body must deserialize to and equal
match Func A do |req| ... callback returning a truthy value

An item with none of these matches every request. Every matcher on one item must match for that item to match, and each item registers a separate mock, first-registered winning on overlap -- which is how a specific matcher and a fallback for the same path are expressed together.

Responding

respond: is required. It takes either a dict or a do |req| ... callback returning one, built from the request that matched.

Key Type Meaning
status Int Status code, defaulting to 200
headers Dict Response headers
body Str|Bin Raw response body
json Response body, JSON-serialized

Expectations

expect: states how many matching requests the item should receive, as an Int or a range, and name: labels the item in the resulting failure message. The count is checked at the end of a scoped block, and on demand via Mock.verify.

The returned Mock covers every item this call registered.

Errors

Exception Condition
RuntimeError No items were given
MissingKeyError An item has no respond:
ValueError An item's path_regex is invalid
ValueError An item's method is not a valid HTTP method
ValueError An item's path contains ? or a host
RuntimeError An item's expect: is unsatisfied at block end

Example

server.mock
  - method: POST
    path: /echo
    respond: do |req| $
      status: 200
      body: $req.body

Two items in one call, the specific one first:

server.mock
  - method: GET
    path: /users/42
    headers:
      authorization: "Bearer valid"
    respond:
      status: 200
  - method: GET
    path: /users/42
    respond:
      status: 401

The script owns the returned handle:

let handle = server.mock
  - method: GET
    path: /users/42
    respond:
      status: 200

http.get (server.url / "/users/42")
handle.unmount()

mock[R] ...args -> R overload 2 of 2

Registers mocks for the duration of a block, which is called with the Mock handle. The mocks are unmounted when the block returns, however it exits.

The items are those of the form without a block, and the block is written last at the call site, as a trailing do block.

server.mock
  - method: GET
    path: /health
    respond:
      status: 200
  do |handle|
    http.get (server.url / "/health")
    handle.verify()

Parameters

NameTypeDescription
...args {*Dict[{respond: Value, ...}], (Mock) -> R} Mock items followed by the block.

received_requests() -> Array[Request]

Every request the server received, whichever mock matched it -- or none.

Use Mock.received to scope this to one mock call.

reset()

Unmounts every mock registered on the server, scoped or not, and forgets every request it received.

Their Mock handles then report no requests, and Mock.verify fails for items with expect:.