🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
The @Captor annotation in Mockito is used to create an argument captor, which is a special type of object that can capture argument values passed to mock methods. This is particularly useful when you want to verify that a method was called with specific arguments or to inspect the arguments passed to a mock method. In this tutorial, we will demonstrate step by step how to use the @Captor annotation in Mockito.
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>
Example Scenario
We will create a UserService class that has a dependency on a UserRepository. Our goal is to test the UserService methods using Mockito's @Captor annotation to capture and verify the arguments passed to the UserRepository methods.
UserService and UserRepository Classes
First, create the User class, the UserRepository interface, and the UserService class.
public class User {
private String name;
private String email;
// Constructor, getters, and setters
public User(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public interface UserRepository {
void saveUser(User user);
User findUserByEmail(String email);
}
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void registerUser(String name, String email) {
User user = new User(name, email);
userRepository.saveUser(user);
}
public User getUserByEmail(String email) {
return userRepository.findUserByEmail(email);
}
}
JUnit 5 Test Class with Mockito
Create a test class for UserService 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.ArgumentCaptor;
import org.mockito.Captor;
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 UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Captor
private ArgumentCaptor<User> userCaptor;
@Test
public void testRegisterUser() {
// Given
String name = "John Doe";
String email = "john.doe@example.com";
// When
userService.registerUser(name, email);
// Then
verify(userRepository).saveUser(userCaptor.capture());
User capturedUser = userCaptor.getValue();
assertEquals(name, capturedUser.getName());
assertEquals(email, capturedUser.getEmail());
}
@Test
public void testGetUserByEmail() {
// Given
String email = "jane.doe@example.com";
User mockUser = new User("Jane Doe", email);
when(userRepository.findUserByEmail(email)).thenReturn(mockUser);
// When
User result = userService.getUserByEmail(email);
// Then
assertNotNull(result);
assertEquals("Jane Doe", result.getName());
assertEquals(email, result.getEmail());
verify(userRepository).findUserByEmail(email);
}
}
Explanation
Annotations:
@ExtendWith(MockitoExtension.class): Integrates Mockito with JUnit 5, enabling the use of Mockito annotations.@Mock: Creates a mock instance of theUserRepositoryinterface. This mock will be used to simulate the behavior of the actual repository without needing a concrete implementation.@InjectMocks: Injects the mockUserRepositoryinto theUserServiceinstance.@Captor: Creates anArgumentCaptorfor capturingUserobjects.
testRegisterUser():
- Given: Sets up the name and email for a new user.
- When: Calls the
registerUsermethod on theUserServiceinstance. - Then:
- Verifies that the
saveUsermethod was called on theUserRepositorywith aUserobject. - Captures the
Userobject passed to thesaveUsermethod using theuserCaptor. - Asserts that the captured user's name and email are correct.
- Verifies that the
testGetUserByEmail():
- Given: Sets up a mock
Userobject and configures theUserRepositoryto return the mock user when thefindUserByEmailmethod is called. - When: Calls the
getUserByEmailmethod on theUserServiceinstance. - Then:
- Asserts that the returned user is not null and that the name and email are correct.
- Verifies that the
findUserByEmailmethod was called on theUserRepositorywith the expected email.
In the above code example, the UserRepository interface does not have an implementation class. This is intentional because Mockito is used to create a mock of the UserRepository. The mock simulates the behavior of the UserRepository without needing an actual implementation.
When using Mockito, you do not need a concrete implementation of the interface you are mocking. Mockito will generate a mock object that implements the interface and allows you to specify the behavior of its methods.
Conclusion
The @Captor annotation in Mockito allows you to capture and inspect arguments passed to mock methods, providing more control and insight into your unit tests. By using @Captor, you can verify that methods are called with the correct arguments and inspect the values passed to them. This step-by-step guide demonstrated how to effectively use the @Captor annotation in your unit tests, covering different scenarios to ensure comprehensive testing of the UserService class.
Comments
Post a Comment
Leave Comment