Intermediate Reading time: ~3 min

Mocking

Mockito, @MockBean, @SpyBean, test doubles

Mocking

Mocking is not about replacing everything; it is about deliberately drawing the boundary of a test.

1. Definition

Mockito and @MockBean let you isolate dependencies. The distinction matters: a plain Mockito mock lives in the test, while @MockBean replaces a bean inside the Spring context.

2. Core Concepts

What happens underneath

Mockito and @MockBean let you isolate dependencies. The distinction matters: a plain Mockito mock lives in the test, while @MockBean replaces a bean inside the Spring context.

When it is useful

Mocking is not about replacing everything; it is about deliberately drawing the boundary of a test. In interviews, highlight common use cases and the related Spring annotations.

What interviewers ask

Common questions cover Mocking trade-offs, debugging, and production pitfalls.

3. Practical Usage

  • Use Mocking when the problem truly calls for it.
  • Look at configuration and annotations together because both shape runtime behavior in Spring.
  • During debugging always inspect startup logs, the bean graph, and active profiles.
  • Prefer small components with clear responsibilities.
  • In interviews, mention the production trade-off, not only the annotation name.

4. Code Examples

The following example demonstrates Mocking with real Spring annotations.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.mockito.BDDMockito.given;

@WebMvcTest(UserController.class)
class UserControllerTest {
    @MockBean
    UserService userService;

    @Autowired
    org.springframework.test.web.servlet.MockMvc mockMvc;

    @Test
    void shouldUseMockedService() {
        given(userService.findName(1L)).willReturn("Ada");
    }
}

Too many mocks can produce brittle tests that are tied to implementation details instead of behavior.

5. Trade-offs

  • Convention vs explicit configuration — Spring speeds development through convention, but sometimes explicit control is required for predictable behavior.
  • Fast development vs transparency — Less boilerplate is good, but too much framework magic can make debugging harder.
  • Abstraction vs control — Higher abstraction accelerates development, but you still need to understand low-level behavior.

6. Common Mistakes

  • Memorizing annotations without understanding runtime behavior.
  • Changing defaults without understanding the consequences.
  • Keeping oversized components with weak boundaries.
  • Ignoring logs and diagnostic tooling.
  • Not aligning the test strategy with the specific layer.

7. Senior-level Insights

  • A senior Spring engineer also looks at which proxy, bean post-processor, or filter is active under the hood.
  • Most hard bugs are not about annotation names but about lifecycle and ordering.
  • In production thinking, startup time, memory, observability, and rollback strategy all matter.

8. Glossary

  • Mocking: A Spring concept or mechanism related to this topic.
  • Bean: An object managed by Spring.
  • Proxy: An intermediate object that can add behavior.
  • Configuration: Properties or bean definitions that shape runtime behavior.
  • Context: The current application container state in Spring.

9. Cheatsheet

  • Mocking is not about replacing everything; it is about deliberately drawing the boundary of a test.
  • Understand the underlying lifecycle.
  • In interviews, mention the trade-off, not just the annotation.
  • For production bugs, start with logs, bean graph, and active profiles.
  • The simplest working solution is often the best one.

🎮 Games

8 questions