Saturday, 18 October 2025

Deep Dive into JUnit + Mockito in Spring Boot

In Spring Boot, we usually use JUnit 5 along with Mockito to write unit and integration tests.
Below are some of the most important annotations and tools you’ll come across while testing your application.


๐Ÿงช @Mock

  • This annotation creates a mock object (a dummy object) for a dependency.

  • It does not run any real logic — instead, you define what it should return when a method is called.

๐Ÿ‘‰ Example:

@Mock private UserRepository userRepository;

Here, the real database calls are not made. We can use Mockito’s when(...).thenReturn(...) to specify what this mock should return.


๐Ÿงฐ @InjectMocks

  • This creates a real instance of the class under test and automatically injects the mock dependencies (created with @Mock) into it.

  • This is mainly used when you are testing the Service layer or any class that has dependencies.

๐Ÿ‘‰ Example:

@ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @InjectMocks private UserService userService; // <-- mock repository will be injected here @Test void testFindUser() { when(userRepository.findById("101")) .thenReturn(Optional.of(new User("101", "Aamir"))); User user = userService.getUser("101"); assertThat(user.getName()).isEqualTo("Aamir"); } }

๐Ÿ“Œ Why use @InjectMocks?
Without it, you would have to manually create the object like:

UserService userService = new UserService(userRepository);

@InjectMocks makes this automatic and cleaner.


๐ŸŒฟ @MockBean

  • This is used in Spring Test Context (e.g., with @WebMvcTest or @SpringBootTest).

  • It registers a mock bean in the Spring ApplicationContext, replacing the actual bean.

๐Ÿ‘‰ Example:

@WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; // replaces the real service in the Spring context @Test void testGetUser() throws Exception { when(userService.getUser("123")).thenReturn(new User("123", "Aamir")); mockMvc.perform(get("/users/123")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Aamir")); } }

๐Ÿ“Œ @MockBean vs @Mock:

  • @Mock → creates a Mockito mock object only (no Spring involved).

  • @MockBean → creates a mock and replaces the actual Spring bean with it in the ApplicationContext.


๐Ÿ•ธ️ @WebMvcTest

  • This annotation loads only the Spring MVC components required for controller testing.

  • It does not load the entire application context (like services, repositories, etc.).

  • This is used to test the Controller layer in isolation.

๐Ÿ‘‰ Example:

@WebMvcTest(UserController.class) class UserControllerTest { ... }

๐Ÿงญ MockMvc

  • MockMvc allows you to simulate HTTP requests (GET, POST, etc.) without actually starting the server.

  • You can test endpoints, status codes, and responses just like calling APIs from a browser or Postman.

๐Ÿ‘‰ Example:

mockMvc.perform(get("/users/1") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Aamir"));

๐Ÿ“ Summary Table

AnnotationPurposeScope
@MockCreates a Mockito mock (no Spring involved)Plain Unit Tests
@InjectMocksCreates real instance and injects mocks into itPlain Unit Tests
@MockBeanRegisters mock in Spring ApplicationContext, replacing real beanSpring Context Tests
@WebMvcTestLoads only controller-related beans for testingController Layer Testing
MockMvcSimulates HTTP requests without running the serverController Layer Testing

✅ How to Choose

  • Service Layer Testing → Use @Mock + @InjectMocks

  • Controller Layer Testing → Use @WebMvcTest + @MockBean + MockMvc

  • Repository Layer Testing → Use @DataJpaTest (integration with in-memory DB)


This clear separation helps keep tests fast, maintainable, and focused on each layer.

No comments:

Post a Comment