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
| Name | Type | Description |
|---|---|---|
func |
((Server) -> R) |
Called with the Server. |
Example
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
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
| Name | Type | Description |
|---|---|---|
...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
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
| Name | Type | Description |
|---|---|---|
...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:.