In JUnit 5, testing with mock objects has been significantly enhanced through the use of Mockito. Two essential annotations for working with Mockito are @Mock and @Captor. The @Mock annotation helps create mock instances of dependencies, while @Captor allows capturing argument values that are passed to methods.
In this article, we will learn how to inject the @Mock and @Captor annotations into JUnit 5 method parameters to simplify test setups and improve readability.
Prerequisites:
- Basic understanding of the Java and JUnit 5.
- Familiarity with Mockito for creating the mock objects.
- Maven for building dependency management.
- JDK and IntelliJ IDEA installed in your system.
Setting Up the Environment
To use Mockito with JUnit 5, add the following Maven dependencies to the pom.xml file:x
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
Main Concept: Injecting @Mock and @Captor in JUnit 5 Method Parameters
In JUnit 5, testing with mock objects is made easy with the help of Mockito. The use of @Mock and @Captor allows us to create mocks and capture arguments efficiently, helping us simulate and verify interactions between objects.
What is @Mock?
@Mock is an annotation provided by Mockito for creating mock instances of classes or interfaces. A mock is a simulated version that allows us to mimic the behavior of real objects without invoking their actual implementations. This is particularly useful in unit testing, where we want to isolate the class being tested from its dependencies.
What is @Captor?
@Captor simplifies the process of capturing arguments passed to methods. It wraps the ArgumentCaptor, a utility that helps verify that methods were called with specific arguments.
Implementation to Inject @Mock and @Captor in JUnit 5 Method Parameters
In this example project, we will create a setup that demonstrates how to use @Mock and @Captor in JUnit 5 to test interactions between a UserService and a UserRepository.
Step 1: Create a New Maven Project
Create a new Maven project using IntelliJ IDEA with the following options:
- Name:
mock-captor-example - Build System: Maven
Click on the Create button.

Project Structure
After project creation done successfully, set up the file structure like shown in the below image:

Step 2: Add the JUnit 5 dependencies to pom.xml
Open the pom.xml file and add the necessary dependencies as described earlier.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gfg</groupId>
<artifactId>mock-captor-example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- JUnit 5 Dependency -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- Mockito Dependency -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<!-- Mockito JUnit 5 Integration -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<!-- AssertJ for Fluent Assertions -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Step 3: Create the User Class
Create the User class and this is a simple class that represents the User.
package com.gfg;
// Represents a User with name and email attributes
public class User {
private String name; // User's name
private String email; // User's email
public User(String name, String email) {
this.name = name;
this.email = email;
}
// Getter for name
public String getName() {
return name;
}
// Getter for email
public String getEmail() {
return email;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Setter for email
public void setEmail(String email) {
this.email = email;
}
}
Step 4: Create the UserRepository Interface
Create the UserRepository Interface and this interface simulates the database operations.
package com.gfg;
// Interface representing user repository operations
public interface UserRepository {
void update(int id, User user); // Method to update a user
}
Step 5: Create the UserService Class
Create the UserService class and this class contains the bussiness logic for updating a user.
package com.gfg;
// UserService class to manage user-related operations
public class UserService {
private final UserRepository userRepository; // Dependency on UserRepository
public UserService(UserRepository userRepository) {
this.userRepository = userRepository; // Constructor injection of UserRepository
}
// Method to update a user's information
public void updateUser(int id, User user) {
userRepository.update(id, user); // Calls the update method on the repository
}
}
Step 6: Main Class
The MainApplication class serves as the entry point for demonstration.
package com.gfg;
// Main application to demonstrate user updating
public class MainApplication {
public static void main(String[] args) {
// Create a mock UserRepository for demonstration
UserRepository userRepository = new UserRepository() {
@Override
public void update(int id, User user) {
// Print statements to simulate database update operation
System.out.println("Updating user with ID: " + id);
System.out.println("Name: " + user.getName());
System.out.println("Email: " + user.getEmail());
}
};
// Create the UserService instance with the mock repository
UserService userService = new UserService(userRepository);
// Create a new user
User user = new User("John Doe", "john.doe@example.com");
// Update user information using the service
userService.updateUser(1, user);
}
}
Step 7: Create the UserServiceTest class
Create the UserServiceTest class and this is the test class where we use @Mock and @Captor.
import com.gfg.User;
import com.gfg.UserRepository;
import com.gfg.UserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.eq;
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@InjectMocks
private UserService userService;
@Mock
private UserRepository userRepository;
@Captor
private ArgumentCaptor<User> userCaptor;
@Test
void testUpdateUser() {
// Create a User object
User user = new User("Jane Doe", "jane.doe@example.com");
// Call the updateUser method
userService.updateUser(1, user);
// Verify that userRepository.update was called with the correct User
verify(userRepository).update(eq(1), userCaptor.capture());
// Get the captured User
User capturedUser = userCaptor.getValue();
// Perform assertions on the captured User object
assertThat(capturedUser.getName()).isEqualTo("Jane Doe");
assertThat(capturedUser.getEmail()).isEqualTo("jane.doe@example.com");
}
}
Explanation:
@ExtendWith(MockitoExtension.class): Enables Mockito’s JUnit 5 integration, allowing the use of annotations like@Mock,@Captor, and@InjectMocks.@InjectMocks: Creates an instance ofUserServiceand injects the mockUserRepositoryinto it.@Mock: Creates a mock object ofUserRepository, which is used in theUserServiceclass.@Captor: Initializes anArgumentCaptorto capture arguments passed to theupdatemethod of theUserRepository.- The
testUpdateUser()method:- Creates a
Userobject with test data. - Calls the
updateUsermethod to simulate updating a user. - Verifies that the
updatemethod of theuserRepositorywas called with the expected user. - Uses assertions to check that the captured
Userobject has the correct name and email.
- Creates a
Step 8: Run the Application
After completing the project, run the application, and it will start at port 8080.

Step 9: Running the Tests
We will now run the UserServiceTest using the below command:
mvn testOutput:

This example project demonstrates how to use the @Mock and @Captor effectively in the Maven project, ensuring that we can test the interaction between classes in the project.