Files
spring-boot-demo/testing-no-containers/README.md
T

57 lines
3.8 KiB
Markdown

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