← Back to Engineering Notes

May 16, 2026

When WireMock Isn't Enough

WireMock has been the default HTTP mock server for fifteen years, and that's not an accident — it's mature, stable, well-documented, and has a JVM-native API that works inside JUnit. If your team is on the JVM and your test surface is HTTP-only, you should probably keep using it. The honest version of "why we built MockForge" isn't that WireMock is bad — it's that we kept running into specific cases where it stopped being the right tool. This is that list.

The honest comparison

We have a side-by-side feature comparison with WireMock if you want the rapid version. This post is the longer one — the situations where the limits actually matter, not the marketing-page bullets.

Case 1: Your test surface has more than HTTP

WireMock is HTTP-only. If your service consumes Kafka, exposes gRPC, talks WebSocket, or sends SMTP, WireMock covers the HTTP layer and you handle the rest with separate tools — testcontainers for Kafka, hand-rolled fakes for gRPC, an SMTP stub like MailHog for email. Three different config formats, three different test setup patterns, three different things to keep in sync as your spec evolves.

The cost isn't WireMock's failure to do these things — it's never claimed it could. The cost is that the team ends up maintaining four mock systems instead of one, and the failure modes that span protocols (an HTTP request that should trigger a Kafka event that should send an email) become tedious to test in isolation. A single tool that speaks all three lets you write one test for the whole sequence.

Case 2: You're testing failure paths, not happy paths

WireMock's fault simulation is real — it has chunked-response truncation, delay, and a few connection-level faults. It's enough for "what happens when the upstream is slow." It's not enough for "what happens when the upstream returns the wrong content-length, or starts sending chunked data and then stops mid-stream, or drops the TCP connection during the response body."

These aren't theoretical failures — they're the production-incident category. The mock either reproduces them or you find them in production. MockForge's chaos primitives were built explicitly for this surface: partial-response simulation, payload corruption with specific patterns, TCP-level connection errors, per-request matchers so you can target chaos at a single endpoint without affecting the rest of the test.

If your testing is purely contract verification ("did the endpoint return 200 with the right shape"), this difference doesn't matter. If you're testing resilience, it's the whole point.

Case 3: Realistic data variability matters

WireMock's response bodies are static — you save the response you want, the mock returns it. Templating is available but you write the rules. For tests that depend on volume — "process 10,000 orders, verify the throughput" — the static-response model means every order looks identical, which papers over the data-shape variability your real production system has to handle.

MockForge's data synthesis goes further: faker-driven generation against the OpenAPI schema, optional drift simulation that shifts response shapes over time the way real upstream APIs do, and AI-assisted generation for cases where realistic content (a customer comment, an address, a product description) matters more than schema correctness. Whether this matters depends on whether your tests are about data shape or data substance.

Case 4: You're outside the JVM

WireMock is Java-first. It runs standalone or in Docker, so language doesn't strictly matter — but the documented test integration is JUnit, the rule API is Java, and the strongest stories are in Spring projects. Outside the JVM, you're using it as a network service from your test code, which works but feels like a workaround.

If your stack is Go, Rust, Node, or Python — and especially if your team is uneasy about a JVM in CI — the calculus changes. There's nothing wrong with running WireMock in Docker from a Go test, but it's friction you may not need.

When WireMock is still the right call

A few cases where switching would be a step backward:

How to know which side you're on

A useful exercise: list the failure modes your tests are supposed to catch. If they're all variations on "did the endpoint return the right thing," WireMock is fine. If they include "what happens when this Kafka topic is slow," "what does the WebSocket client do when the server closes mid-message," or "did the SMTP send actually fire after the order succeeded" — that's MockForge's surface, and the multi-protocol design exists exactly for those tests.

The right mock tool is the one that turns a 30-line custom fake into a five-line config. For HTTP-only teams, that's frequently still WireMock — and that's fine. We just kept watching teams accumulate four or five custom fakes around it as their stack grew, and that was the gap we set out to close.