Mockito in JUnit
Mockito is a popular Java framework used in JUnit testing to create mock objects. These mock objects simulate real dependencies, making unit testing faster, isolated, and more reliable.
Why Use Mockito?
- Isolate dependencies: Avoid calling actual services, databases, or APIs.
- Improve test performance: No need to connect to external systems.
- Control method behavior: Define return values for methods.
- Verify interactions: Ensure methods are called with expected parameters.
Basic Mockito Annotations
1️⃣ @Mock
→ Creates a mock object.
@Mockprivate DepartmentService departmentService;
2️⃣ @InjectMocks
→ Injects mock objects into the class being tested.
@InjectMocks
private DepartmentController departmentController;
3️⃣ @BeforeEach
→ Initializes mocks before each test.
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
Example: Unit Test for DepartmentController
@ExtendWith(MockitoExtension.class) // JUnit 5 (JUnit Jupiter)
public class DepartmentControllerTest {
@Mock
private DepartmentService departmentService;
@InjectMocks
private DepartmentController departmentController;
private Department department;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
department = Department.builder()
.departmentId(1L)
.departmentName("IT")
.departmentAddress("New York")
.departmentCode("IT-001")
.build();
}
@Test
void testSaveDepartment() {
when(departmentService.saveDepartment(any(Department.class))).thenReturn(department);
Department savedDepartment = departmentController.saveDepartment(department);
assertNotNull(savedDepartment);
assertEquals("IT", savedDepartment.getDepartmentName());
}
@Test
void testFetchDepartmentById() throws DepartmentNotFoundException {
when(departmentService.fetchDepartmentById(1L)).thenReturn(department);
Department foundDepartment = departmentController.fetchDepartmentById(1L);
assertNotNull(foundDepartment);
assertEquals(1L, foundDepartment.getDepartmentId());
}
@Test
void testDeleteDepartmentById() {
String response = departmentController.deleteDepartmentById(1L);
assertEquals("Department deleted Successfully!!", response);
verify(departmentService, times(1)).deleteDepartmentById(1L);
}
}
Key Mockito Methods
when(...).thenReturn(...)
→ Mock method behavior.when(departmentService.fetchDepartmentById(1L)).thenReturn(department);
any(Class.class)
→ Match any argument of that class.when(departmentService.saveDepartment(any(Department.class))).thenReturn(department);
verify(..., times(n))
→ Ensure a method was called n
times.verify(departmentService, times(1)).deleteDepartmentById(1L);
doThrow(...).when(...).method()
→ Simulate exceptions.doThrow(new DepartmentNotFoundException("Not Found")).when(departmentService).fetchDepartmentById(2L);
Mockito vs. Real Objects
Feature Real Object Mockito Mock Calls real methods? ✅ Yes ❌ No Affects real data? ✅ Yes ❌ No Faster execution? ❌ No ✅ Yes Dependency isolation? ❌ No ✅ Yes
1) We can write JUnit tests for a Spring Boot Controller layer using @WebMvcTest
with Mockito, while the backend uses MS SQL Server(relational database).
✅ Scenario Overview for relational databases
-
Database: MS SQL Server (via Spring Data JPA)
-
Test: Controller using
@WebMvcTest
-
Mocking:
UserService
-
HTTP testing:
MockMvc
User.java
(Entity)๐ฆ 2. UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
}
๐ฆ 3. UserService.java
@Servicepublic class UserService {
@Autowired
private UserRepository userRepository;
public User saveUser(User user) {
return userRepository.save(user);
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public Optional<User> getUserById(Long id) {
return userRepository.findById(id);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
๐ฆ 4. UserController.java
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
return new ResponseEntity<>(userService.saveUser(user), HttpStatus.CREATED);
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return ResponseEntity.ok(userService.getAllUsers());
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return userService.getUserById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
๐ Key Point:
in @WebMvcTest
tests, the actual database (MSSQL Or MongoDB) is not involved — we mock the service layer, so it doesn't matter which database is used.
✅ 5. UserControllerTest.java
– @WebMvcTest
+ Mockito
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
private User user;
@BeforeEach
void setUp() {
user = new User();
user.setId(1L);
user.setName("John");
user.setEmail("john@example.com");
}
@Test
void testCreateUser() throws Exception {
when(userService.saveUser(any(User.class))).thenReturn(user);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\", \"email\":\"john@example.com\"}"))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("John"))
.andExpect(jsonPath("$.email").value("john@example.com"));
}
@Test
void testGetAllUsers() throws Exception {
when(userService.getAllUsers()).thenReturn(List.of(user));
mockMvc.perform(get("/api/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(1))
.andExpect(jsonPath("$[0].name").value("John"));
}
@Test
void testGetUserById() throws Exception {
when(userService.getUserById(1L)).thenReturn(Optional.of(user));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("John"));
}
@Test
void testDeleteUser() throws Exception {
doNothing().when(userService).deleteUser(1L);
mockMvc.perform(delete("/api/users/1"))
.andExpect(status().isNoContent());
}
}
๐งช Dependencies Required in pom.xml
Make sure your pom.xml
includes:
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- For JSONPath in tests -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
✅ Summary
Layer Tool Used Notes Controller @WebMvcTest
Tests only controller, not service/repo Service @MockBean
Service is mocked to isolate controller DB MS SQL Not used in controller test
------------------------------------------------------------2)We can write a JUnit + Mockito + @WebMvcTest test class for a Spring Boot Controller that uses MongoDB.✅ Scenario Setup: MongoDB-based User CRUD๐ฆ User.java
@Document(collection = "users")
public class User {
@Id
private String id;
private String name;
private String email;
// Getters and Setters
}
๐ฆ UserRepository.java
public interface UserRepository extends MongoRepository<User, String> {
}
๐ฆ UserService.java same as above
๐ฆ UserController.java same as above
✅ UserControllerTest.java
– JUnit + Mockito + @WebMvcTest same as above
๐ฆ Maven Dependencies (If not already present)
Make sure your test scope dependencies include:
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Mockito Core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
✅ Summary
@WebMvcTest
isolates only the controller.
@MockBean
is used to inject a mocked UserService
—the database (MongoDB) isn’t touched.
Use MockMvc
to simulate HTTP requests.
Since MongoDB is abstracted behind the service, you don't need to mock the repository for controller tests.
3)Can you test private methods with JUnit + Mockito?
๐ด Directly — ❌ NOT recommended
Mockito does NOT support mocking or verifying private methods directly.
It follows the best practice: test public behavior, not internal implementation.
๐ก Indirectly — ✅ YES
Private methods can be tested indirectly by calling public methods that use them.
๐ If you still need to test a private method:
Use Reflection (not recommended for unit tests).
Use PowerMock (now outdated and not compatible with JUnit 5).
Use JUnit 5 + ReflectionTestUtils or similar only for legacy systems.✍️ Example: Testing private method indirectly
javapublic class MyService {
public String process(String input) {
return format(input.toUpperCase());
}
private String format(String value) {
return "[" + value + "]";
}
}
java@Test
public void testProcess() {
MyService service = new MyService();
String result = service.process("hello");
assertEquals("[HELLO]", result); // indirectly tests private format()
}
๐ Common JUnit & Mockito Annotations
Annotation Library Description @Test
JUnit Marks a test method @BeforeEach
/ @Before
JUnit Runs before each test (JUnit 5 / JUnit 4) @AfterEach
/ @After
JUnit Runs after each test @BeforeAll
/ @BeforeClass
JUnit Runs once before all tests @AfterAll
/ @AfterClass
JUnit Runs once after all tests @DisplayName
JUnit 5 Custom name for test method @Nested
JUnit 5 For grouping related test cases @Mock
Mockito Creates a mock object @InjectMocks
Mockito Injects mocks into the tested object @Spy
Mockito Spy on real object (partial mocking) @Captor
Mockito Captures arguments passed to mocks @ExtendWith(MockitoExtension.class)
JUnit 5 + Mockito Enables Mockito annotations in JUnit 5
๐งช Example: Mockito with Annotations
java@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
public void testFindById() {
User user = new User("1", "Swamy");
when(userRepository.findById("1")).thenReturn(Optional.of(user));
Optional<User> result = userService.findById("1");
assertTrue(result.isPresent());
assertEquals("Swamy", result.get().getName());
}
}
๐ Summary
Question Answer Can you test private methods in Mockito? Not directly, only via public methods. Can you mock private methods in Mockito? No, use PowerMock (not recommended). Best practice? Test only public behavior; private methods are implementation details.