Skip to content

Server

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

Constructor

Server() -> Server

Starts a server.

Server func -> R

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

The bound socket address, such as 127.0.0.1:41823.

url @ url.Url

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

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 when the item is unmounted -- at the end of a scoped block, or on Mock.unmount -- 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
RuntimeError An item's expect: is unsatisfied on unmount

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

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, (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()

Removes every mock registered on the server and forgets every request it received.