testing-no-containers
Companion project for the article Testing Spring Boot 4 Without Containers: WireMock, MockWebServer and @MockitoBean on ankurm.com.
Every console block quoted in the article came out of docs/output/. These are real mvn test
and javac transcripts, not retyped output — including two real, captured failures (a
NoClassDefFoundError from a bad WireMock dependency combination, and a @MockBean compiler
error) that are as much the point of the post as the passing tests are.
There is deliberately no docs/NN-topic.md chapter folder: the deeper material lives in
collapsible "going deeper" sections inside the article itself, next to the paragraph each one
extends. docs/output/ (captured transcripts) is the one thing that still lives under docs/.
Versions
| Spring Boot | 4.1.1 |
| Spring Framework | 7.0.9 |
| WireMock | 3.13.2 (wiremock-standalone; the 4.0.0 line is beta-only as of this writing — see the article) |
| OkHttp MockWebServer | 5.5.0 (mockwebserver3-junit5) |
| Mockito | 5.23.0 (Spring Boot 4.1.1's own managed version, via mockito-bom) |
| JDK | 25 (GraalVM CE 25.4.4.1.1) |
| Maven | 3.9 |
Quickstart
export JAVA_HOME=/path/to/jdk-25
mvn test # runs everything below; no Docker, no Testcontainers, no running server required
What's demonstrated
| Area | Where |
|---|---|
@MockBean is completely removed in Spring Boot 4 (not deprecated — the package is gone) |
docs/output/01-mockbean-removed-compiler-error.txt |
@MockitoBean/@MockitoSpyBean (Spring Framework 7's replacement) mocking a collaborator with no running server |
GreetingMockitoBeanATest.java, GreetingMockitoBeanBTest.java |
The identical @MockitoBean override set is the ApplicationContext cache key: two classes with the same override reuse one context |
GreetingMockitoBeanATest.java / GreetingMockitoBeanBTest.java, proven via real org.springframework.test.context.cache DEBUG log lines |
@MockitoSpyBean is a different override set than @MockitoBean, even against the same type — a genuine cache miss |
GreetingMockitoSpyBeanCTest.java |
WireMock fault injection (Fault.CONNECTION_RESET_BY_PEER, withFixedDelay) against a real RestClient |
QuoteClientWireMockTest.java |
| The wrong way and the right way to pull a WireMock server into the classpath in the 3.x line | docs/output/02-wiremock-bare-fatalstartup.txt, docs/output/03-wiremock-plus-jetty12-noclassdef.txt, pom.xml |
MockWebServer's lower-level socket primitives (SocketEffect.ShutdownConnection) for genuinely severing a connection mid-response, vs. just sending truncated JSON |
QuoteClientMockWebServerTest.java |
Boot 4.1's ClientHttpRequestFactoryBuilder/HttpClientSettings API (not the Boot-3-era ClientHttpRequestFactorySettings/ClientHttpRequestFactories pair, which no longer exists) |
QuoteClient.java |
Captured output
| File | What it shows |
|---|---|
01-mockbean-removed-compiler-error.txt |
a standalone javac run against code importing org.springframework.boot.test.mock.mockito.MockBean: "package ... does not exist" |
02-wiremock-bare-fatalstartup.txt |
the bare wiremock artifact alone: FatalStartupException, no HttpServerFactory on the classpath |
03-wiremock-plus-jetty12-noclassdef.txt |
wiremock + wiremock-jetty12 together: a mismatched-Jetty-version NoClassDefFoundError at server startup |
04-full-test-run-passing.txt |
the real, full mvn clean test run: all 8 tests passing, including the real org.springframework.test.context.cache DEBUG lines that prove the hit/miss behavior |
Nothing here needs Docker, a running server, or a network connection outside the JVM — that is the whole premise of the post.