Skip to content

HTTP · gRPC · CLI · Docker

vlatteMock HTTP and gRPC APIs for your tests

Start real mock servers inside Go tests, or run them from YAML and JSON for apps in any language. Simulate responses, streaming, stateful flows and network failures, and verify what your client sent.

The binary and Docker image need no Go installation.

go get github.com/caffeine-projects/vlatte@v1.1.0
go
func 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)
}
go
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())
}
yaml
# 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
sh
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"}

Run it your way

The same mocks, in a test, from files, or in a container.

  • In Go tests

    A server per test, on a free port, closed when the test ends.

  • From mock files

    A standalone binary serves YAML or JSON mocks for web, mobile and backend apps. No Go installation needed.

  • In Docker Compose

    Run the same mock files next to your app locally or in CI.

go
// go get github.com/caffeine-projects/vlatte@v1.1.0
m := mockhttp.MustNew()
m.MustStart()
t.Cleanup(m.Close)

m.MustMock(mockhttp.Getf("/health").Reply(mockhttp.OK()))
sh
# Install the binary for your platform; see Installation.

# Serves the mock files of testdata/vlatte/_mocks.
vlatte --addr=:8080
yaml
services:
  payments:
    image: ghcr.io/caffeine-projects/vlatte
    ports: ["8080:8080"]
    volumes:
      - ./mocks:/vlatte/testdata/vlatte/_mocks:ro

Mocks that behave like the real thing

Everything a test needs from a server it doesn't own: the right answer, the wrong one, and the slow one.

HTTPS without the certificate dance

MustStartTLS 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 →
go
m := mockhttp.MustNew()
m.MustStartTLS() // m.URL() starts with https://
t.Cleanup(m.Close)
go
m := mockgrpc.MustNew()
m.MustStartTLS()
t.Cleanup(m.Close)

conn := m.MustDial() // trusts the server's certificate
go
m := mockhttp.MustNew(mockhttp.Setup().
	TLSMutual("localhost.pem", "localhost-key.pem", "ca.pem"))
m.MustStartTLS()
sh
vlatte --https

Break things on purpose

Clients 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 →
go
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")),
)
yaml
request:
  method: GET
  path: /report
response:
  status: 200
  body_file: report.csv
pipes:
  - type: bandwidth
    rate: 3g

Mocks your coding agent can drive

Over 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.

Give your agent the documentation index at /llms.txt, or the focused Markdown pages it links to, so it can find the APIs and examples for its task.

Coding Agents →
json
{"mcpServers": {"vlatte": {"command": "vlatte", "args": ["mcp", "--mock-files=mocks/*.yaml"]}}}
go
api := admin.MustNew(admin.MCP())
m := mockhttp.MustNew(mockhttp.Setup().Admin(api))
m.MustStart()

fmt.Println(m.AdminURL() + "/mcp") // Streamable HTTP

Toolbox

More of what comes in the box.

Ready to mock?

Write your first mock in a Go test, or serve one from a file.