# testing-no-containers Companion project for the article **[Testing Spring Boot 4 Without Containers: WireMock, MockWebServer and @MockitoBean](https://ankurm.com/)** on **[ankurm.com](https://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 ```bash 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.