Introduction
@Mock
annotation is a shorthand way of creating mock objects. Instead of manually creating a mock using Mockito.mock(Class)
, you can annotate a field with @Mock
to automatically create a mock instance.In many software applications, business logic and data access logic are separated into service and repository layers, respectively. When testing the service layer, it's often beneficial to mock the repository to ensure that it is tested in isolation.
This tutorial will demonstrate step-by-step how to mock the EmployeeService
and EmployeeRepository
using Mockito's @Mock
annotation and the Given/When/Then format.
Maven Dependencies
To use Mockito with JUnit 5, add the following dependencies to your pom.xml
file:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Step-by-Step Example
Step 1: Create the Employee and EmployeeRepository Classes
First, create the Employee
class and the EmployeeRepository
interface.
public class Employee {
private String name;
private String position;
// Constructor
public Employee(String name, String position) {
this.name = name;
this.position = position;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
public interface EmployeeRepository {
Employee findEmployeeByName(String name);
}
Step 2: Create the EmployeeService Class
Create the EmployeeService
class that depends on the EmployeeRepository
.
public class EmployeeService {
private final EmployeeRepository employeeRepository;
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public Employee getEmployee(String name) {
return employeeRepository.findEmployeeByName(name);
}
}
Step 3: Set Up JUnit 5 Test Class with Mockito
Create a test class for EmployeeService
using JUnit 5 and Mockito.
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class EmployeeServiceTest {
@Mock
private EmployeeRepository employeeRepository;
@InjectMocks
private EmployeeService employeeService;
@Test
public void testGetEmployee() {
// Given
Employee mockEmployee = new Employee("John Doe", "Developer");
when(employeeRepository.findEmployeeByName("John Doe")).thenReturn(mockEmployee);
// When
Employee result = employeeService.getEmployee("John Doe");
// Then
assertNotNull(result);
assertEquals("John Doe", result.getName());
assertEquals("Developer", result.getPosition());
verify(employeeRepository).findEmployeeByName("John Doe");
}
}
Explanation
Annotations:
@ExtendWith(MockitoExtension.class)
: Integrates Mockito with JUnit 5, enabling the use of Mockito annotations.@Mock
: Creates a mock instance of theEmployeeRepository
interface.@InjectMocks
: Injects the mockEmployeeRepository
into theEmployeeService
instance.
Given:
Employee mockEmployee = new Employee("John Doe", "Developer");
: Creates a mockEmployee
object.when(employeeRepository.findEmployeeByName("John Doe")).thenReturn(mockEmployee);
: Configures the mockEmployeeRepository
to return the mockEmployee
when thefindEmployeeByName
method is called with the argument "John Doe".
When:
Employee result = employeeService.getEmployee("John Doe");
: Calls thegetEmployee
method on theEmployeeService
instance.
Then:
assertNotNull(result);
: Asserts that the result is not null.assertEquals("John Doe", result.getName());
: Asserts that the name of the returnedEmployee
is "John Doe".assertEquals("Developer", result.getPosition());
: Asserts that the position of the returnedEmployee
is "Developer".verify(employeeRepository).findEmployeeByName("John Doe");
: Verifies that thefindEmployeeByName
method was called with the expected argument.
Additional Scenarios
Scenario 1: Employee Not Found
In this scenario, we will test the case where the employee is not found in the repository.
@Test
public void testGetEmployee_NotFound() {
// Given
when(employeeRepository.findEmployeeByName("Jane Doe")).thenReturn(null);
// When
Employee result = employeeService.getEmployee("Jane Doe");
// Then
assertNull(result);
verify(employeeRepository).findEmployeeByName("Jane Doe");
}
Scenario 2: Employee with Different Position
In this scenario, we will test the case where the employee's position is different from the expected value.
@Test
public void testGetEmployee_DifferentPosition() {
// Given
Employee mockEmployee = new Employee("John Doe", "Manager");
when(employeeRepository.findEmployeeByName("John Doe")).thenReturn(mockEmployee);
// When
Employee result = employeeService.getEmployee("John Doe");
// Then
assertNotNull(result);
assertEquals("John Doe", result.getName());
assertEquals("Manager", result.getPosition());
verify(employeeRepository).findEmployeeByName("John Doe");
}
Conclusion
The @Mock
annotation in Mockito simplifies the creation and injection of mock objects in unit tests. By using @Mock
and @InjectMocks
, you can easily set up mock dependencies and focus on testing the behavior of your code. This step-by-step guide covered different scenarios using the Given/When/Then format to demonstrate how to effectively use the @Mock
annotation in your unit tests.
Comments
Post a Comment
Leave Comment