HTTP · gRPC · CLI · Docker
Real HTTP and gRPC servers for your tests, that answer the way you tell them to. Match any part of a request, reply with templates, record real APIs and break things on purpose. Then serve the same mocks from files.
go get github.com/caffeine-projects/vlattefunc TestCharge(t *testing.T) {
m := mockhttp.MustNew()
m.MustStart()
t.Cleanup(m.Close)
paid := m.MustMock(mockhttp.Postf("/payments").
Header("Authorization", match.HasPrefix("Bearer ")).
Body(match.JSONPath("$.amount", match.GreaterThan(0))).
Reply(mockhttp.Created().
JSON(map[string]any{"id": "pay_1"})))
client := payments.NewClient(m.URL(), "token")
_, err := client.Charge(t.Context(), 42)
require.NoError(t, err)
paid.AssertCalled(t)
}func TestGreeter(t *testing.T) {
m := mockgrpc.MustNew()
m.MustStart()
t.Cleanup(m.Close)
m.MustMock(mockgrpc.Method("greeter.Greeter/SayHello").
Field("name", match.HasPrefix("a")).
Reply(mockgrpc.Message(&pb.HelloReply{Message: "hi ann"})))
client := pb.NewGreeterClient(m.MustDial())
res, err := client.SayHello(t.Context(), &pb.HelloRequest{Name: "ann"})
require.NoError(t, err)
require.Equal(t, "hi ann", res.GetMessage())
}# testdata/vlatte/_mocks/payments_mock.yaml
request:
method: POST
path: /payments
header:
authorization: [hasprefix, "Bearer "]
body: [jsonpath, $.amount, [gt, 0]]
response:
status: 201
header:
content-type: application/json
body: {id: pay_1}vlatte --https --addr=:8443
curl -k https://localhost:8443/payments \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-d '{"amount": 42}'
# 201 {"id":"pay_1"}Everything a test needs from a server it doesn't own: the right answer, the wrong one, and the slow one.
Real servers in your tests. gRPC needs no service implementation: any method, any call type.
Match the method, path, headers, query, forms, files and body, with the same matchers on both protocols.
Build headers and bodies from the request, with functions for JSON, strings, time and hashes.
Proxy a real service once, save what passes through as mock files, and play it back without it.
See how clients cope with slow networks, dribbled bodies, resets, garbage and timeouts.
Mocks that answer by state, for flows that change as they go: a cart that fills, a job that ends.
HTTPS and gRPC over TLS with no certificate to make, or with yours, and client certificates if you like.
Serve mock files with the vlatte command or Docker, and change mocks while they run, over REST or MCP.
The same mocks, in a test, from files, or in a container.
A server per test, on a free port, closed when the test ends.
The vlatte command serves the YAML or JSON files of a folder.
The image serves your mock files next to the app that calls them.
// go get github.com/caffeine-projects/vlatte
m := mockhttp.MustNew()
m.MustStart()
t.Cleanup(m.Close)
m.MustMock(mockhttp.Getf("/health").Reply(mockhttp.OK()))brew install caffeine-projects/tap/vlatte # or go install github.com/caffeine-projects/vlatte/cmd/vlatte@latest
# Serves the mock files of testdata/vlatte/_mocks.
vlatte --addr=:8080services:
payments:
image: ghcr.io/caffeine-projects/vlatte:v0.1.0-rc.1
ports: ["8080:8080"]
volumes:
- ./mocks:/vlatte/testdata/vlatte/_mocks:roMustStartTLS serves HTTPS, or gRPC over TLS, with a certificate built in: no openssl, no files to keep.
Bring your own certificate when you need one, or ask clients for theirs with mutual TLS. The CLI and the Docker image do the same with a flag.
TLS →m := mockhttp.MustNew()
m.MustStartTLS() // m.URL() starts with https://
t.Cleanup(m.Close)m := mockgrpc.MustNew()
m.MustStartTLS()
t.Cleanup(m.Close)
conn := m.MustDial() // trusts the server's certificatem := mockhttp.MustNew(mockhttp.Setup().
TLSMutual("localhost.pem", "localhost-key.pem", "ca.pem"))
m.MustStartTLS()vlatte --httpsClients fail in the ways their servers do. Faults make a mock reset the connection, trickle its body, send garbage or never answer, so you see your retries and timeouts work before production does.
Chaos testing →m.MustMock(
// The first call loses its connection.
mockhttp.Getf("/report").Once().
WirePipe(fault.ConnectionResetByPeer()).
Reply(mockhttp.OK()),
// The retry gets its body over a 3G link.
mockhttp.Getf("/report").Priority(1).
Pipe(fault.Bandwidth(fault.Bandwidth3G)).
Reply(mockhttp.OK().BodyFile("testdata/report.csv")),
)request: {method: GET, path: /report}
response: {status: 200, body_file: report.csv}
pipes:
- type: bandwidth
rate: 3gOver MCP, a coding agent sees every mock, writes new ones, records a real service and checks what your client sent, with the tools the admin API serves.
Start vlatte mcp from the agent's settings, or point it at /mcp on a server that runs already.
{"mcpServers": {"vlatte": {"command": "vlatte", "args": ["mcp", "--mock-files=mocks/*.yaml"]}}}api := admin.MustNew(admin.MCP())
m := mockhttp.MustNew(mockhttp.Setup().Admin(api))
m.MustStart()
fmt.Println(m.AdminURL() + "/mcp") // Streamable HTTPMore of what comes in the box.
Every matcher, in Go and in mock files, and how to write your own.
Record HTTP and gRPC services as mock files, from Go, the CLI or the admin API.
Ready-made setups, such as a server that proxies every request.
Call other services after a mock answers, with templated requests.
What clients sent, to verify in tests or read over the admin API.
JSON schemas that give your editor completion and checks for mock files.
Write your first mock in a Go test, or serve one from a file.