Chapter 21½: inside jev-mock/src — the set, the script and the recorder
Three files: the server itself, and the two ways to give it someone else's lines.
The files, in reading order
- lib.rs: the server.
Recordedis one request as the server saw it: HTTP version, method, path, headers, body.Replyis what to answer:Reply::json(status, body), then.header(name, value),.after(delay)(stall first; a client that gives up resets the stream, whichabandoned()counts) and.after_requests(n)(stall until n requests have arrived, so a test can count what a client sends before its first answer without racing it).raw_bodysends exact bytes instead of the JSON.MockJev::start(respond)serves on127.0.0.1with a certificate for that address;start_for(names, respond)adds host names;start_limited(max_streams, respond)advertisesSETTINGS_MAX_CONCURRENT_STREAMS. Each start makes a fresh CA withrcgen, writes it to a temp directory (ca_file()), and accepts only ALPNh2, as the real endpoint does.- Reading the result:
endpoint(),endpoint_via(host),requests(),connections(),accepts(),peak_in_flight(),abandoned(),pings(). - Making trouble:
goaway()sends GOAWAY on every open connection;ignore_pings_on_next(n)makes the next n connections swallow their PING acknowledgements. Frames, at the bottom, sits between TLS and hyper and reads the plaintext HTTP/2 stream frame by frame. hyper answers PINGs itself, so this is the only place the mock can count them or withhold the replies.
- replay.rs:
FixtureandReplay. A fixture is JSON,{"model", "exchanges": [{"request", "responses": [{"status", "headers": [[name, value]], "body"}]}]}, withrequestandbodyas the bytes on the wire, as text.Fixture::parse,loadandto_jsonread and write it.Replay::new(&fixture).responder()serves each request's responses in order;misses()lists what it lacked, andassert_complete()panics naming them, as the last handle'sDropdoes unless the test is already panicking. - forward.rs:
Forward::new(upstream, api_key, model)and itsresponder(), which sends each request upstream withblock_in_place(so the mock must run on a multi-threaded tokio runtime), one fresh connection per request. Upstream it passes onlycontent-typeandx-typesafe-retry-countand sets its ownauthorization; from the answer it keeps onlycontent-type,x-typesafe-request-id,retry-afterandretry-after-ms. A retried request records its answers in order. A failure to reach the endpoint is answered with a 400 (forward_failed) and recorded as nothing.exchange(body)sends a request built elsewhere;fixture()returns everything recorded so far.
Try it
cargo test -p jev-http --test mock
jev-mock has no tests of its own; its users' tests exercise it.
For the people who maintain it
In this folder
| File | What |
|---|---|
| lib.rs | MockJev, Reply, Recorded, the frame watcher. |
| replay.rs | Fixture, Replay, Response. |
| forward.rs | Forward: record a fixture from a real endpoint. |
| CLAUDE.md | Invariants for agents. |
← Previous: Chapter 21: jev-mock · Up: jev-mock · The end of the guide. Back to Chapter 16: jevcrates