When would you choose @TestBean over @MockitoBean (or @MockitoSpyBean)?
answer
- TestBean = real fake
- MockitoBean = mock + verify
- MockitoSpyBean = wrap real bean
- fake vs stubbing readability
- no Mockito / final-class friendly
basics
~20 sUse @TestBean when you want a real hand-written fake/stub with deterministic behaviour and no Mockito. Use @MockitoBean for a Mockito mock you configure with when/verify, and @MockitoSpyBean to wrap a real bean and spy on it.
solid answer
~50 sAll three are Spring 6.2 bean-override annotations, but they differ in what they inject. @TestBean injects an instance you construct in a static factory method — a real fake or stub, no Mockito involved, so no when/verify and no Mockito proxy limits (works cleanly with final classes, records, sealed types). @MockitoBean injects a Mockito mock: nothing real runs unless you stub it, and you can verify interactions. @MockitoSpyBean wraps the actual bean so real methods run unless overridden. Choose @TestBean when behaviour matters and you want a deterministic collaborator — a fixed Clock, an in-memory repository, a canned gateway — especially when hand-written fakes read better than a pile of stubbings, or when you want to avoid Mockito entirely. Choose @MockitoBean when you need interaction verification or per-test stubbing; @MockitoSpyBean when you want the real bean plus selective overrides.
code
java · 21 lines@SpringBootTest
class CheckoutTests {
// Real deterministic fixture — no stubbing needed.
@TestBean
Clock clock;
static Clock clockTestOverride() {
return Clock.fixed(Instant.parse("2026-01-01T00:00:00Z"), ZoneOffset.UTC);
}
// Mockito mock — configured/verified per test.
@MockitoBean
PaymentGateway paymentGateway;
@Test
void chargesOnce() {
when(paymentGateway.charge(any())).thenReturn(Result.ok());
// ... exercise ...
verify(paymentGateway, times(1)).charge(any());
}
}go deeper
Know @TestBean gives a real fake while @MockitoBean gives a mock.
Articulate the decision guide and that @TestBean avoids Mockito and its proxy limits.
Discuss readability/maintainability trade-offs and final-class/record cases.
Set team conventions on when fakes vs mocks are preferred and why.
## The three Spring 6.2 override annotations Spring 6.2 added a unified bean-override facility with three concrete annotations: - **`@TestBean`** — replace a bean with an instance from a **static factory method** (a real fake/stub). No Mockito. - **`@MockitoBean`** — replace a bean with a **Mockito mock**. Methods return default values until stubbed with `when(...).thenReturn(...)`; you can `verify(...)` interactions. - **`@MockitoSpyBean`** — **wrap** the real bean in a Mockito spy: real methods run unless explicitly stubbed; you can still verify. (These supersede Spring Boot's older `@MockBean`/`@SpyBean`, deprecated in Boot 3.4.) ## Decision guide Pick **@TestBean** when: - You want a **deterministic, real implementation** — e.g. `Clock.fixed(...)`, an in-memory `Map`-backed repository, a stub HTTP client returning canned responses. - The behaviour is complex enough that a hand-written fake is **clearer** than many `when(...)` lines. - You want to **avoid Mockito** or the collaborator is a **final class / record / sealed type** that Mockito can't easily proxy (inline mock-maker helps but a fake sidesteps it entirely). - You don't need interaction verification. Pick **@MockitoBean** when you need **interaction verification** (`verify`), **per-test stubbing**, argument matchers/captors, or to fully isolate a collaborator with zero real logic. Pick **@MockitoSpyBean** when you want the **real bean's behaviour** but need to override or observe one or two methods. ## Trade-offs - **@TestBean** couples the test to a concrete fake you must maintain; but it's fast, deterministic, and mock-framework-free. - **@MockitoBean/@MockitoSpyBean** are quick to set up per test and support verification, but over-stubbing produces brittle, hard-to-read tests. ## Shared mechanics All three select the target bean **by type** by default (with `name`/qualifier disambiguation), participate in the **test context cache key**, and inject into the whole context — the differences are purely in *what* replaces the bean.
- Can you verify interactions on a @TestBean the way you would on a @MockitoBean?Not through Spring — @TestBean injects a plain object with no Mockito recording. If you need verification you must build it into the fake yourself (e.g. a counter) or use @MockitoBean instead.
- What replaced Spring Boot's @MockBean and @SpyBean?@MockitoBean and @MockitoSpyBean (Spring Framework 6.2); Boot deprecated @MockBean/@SpyBean in 3.4.
saying these in an interview costs you the question
- Claiming @TestBean creates a Mockito mock you can stub with when(...)
- Thinking @TestBean supports verify(...) out of the box
- Saying @TestBean and @MockitoSpyBean are the same (spy wraps the real bean; TestBean replaces it with your instance)