In this section, we will explore how to verify interactions with mocks using Mockito in JUnit. Verifying interactions is crucial to ensure that your code behaves as expected, especially when dealing with dependencies and side effects.
Key Concepts
- Mocking: Creating a mock object to simulate the behavior of real objects.
- Verification: Checking if certain methods were called on the mock object with the expected arguments.
Why Verify Interactions?
Verifying interactions helps to:
- Ensure that the correct methods are called.
- Validate the sequence of method calls.
- Confirm that no unexpected interactions occur.
Setting Up Mockito
Before we dive into verifying interactions, ensure you have Mockito set up in your project. Add the following dependencies to your pom.xml if you are using Maven:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>Basic Verification
Example
Let's start with a simple example. Suppose we have a Calculator class with a method add:
We want to verify that the add method is called with specific arguments.
Test Case
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class CalculatorTest {
@Test
public void testAddMethodCalled() {
// Create a mock of Calculator
Calculator calculator = mock(Calculator.class);
// Use the mock object
calculator.add(10, 20);
// Verify that the add method was called with arguments 10 and 20
verify(calculator).add(10, 20);
}
}Explanation
- Creating a Mock:
Calculator calculator = mock(Calculator.class);- This creates a mock object of the
Calculatorclass.
- This creates a mock object of the
- Using the Mock:
calculator.add(10, 20);- We call the
addmethod on the mock object.
- We call the
- Verifying the Interaction:
verify(calculator).add(10, 20);- This verifies that the
addmethod was called with the arguments10and20.
- This verifies that the
Advanced Verification
Verifying Call Count
You can also verify how many times a method was called:
Verifying No Interactions
To ensure that no interactions have occurred with the mock:
Verifying No More Interactions
To verify that no other interactions have occurred after the specified calls:
Verifying in Order
To verify that methods were called in a specific order:
import static org.mockito.Mockito.*;
import org.mockito.InOrder;
import org.junit.jupiter.api.Test;
public class CalculatorTest {
@Test
public void testMethodCallOrder() {
Calculator calculator = mock(Calculator.class);
// Use the mock object
calculator.add(10, 20);
calculator.add(30, 40);
// Create an InOrder verifier for the mock
InOrder inOrder = inOrder(calculator);
// Verify the order of method calls
inOrder.verify(calculator).add(10, 20);
inOrder.verify(calculator).add(30, 40);
}
}Practical Exercise
Exercise
- Create a
UserServiceclass with a methodcreateUser(String username). - Create a test case to verify that the
createUsermethod is called with the argument"john_doe".
Solution
public class UserService {
public void createUser(String username) {
// Logic to create a user
}
}
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
public class UserServiceTest {
@Test
public void testCreateUserCalled() {
// Create a mock of UserService
UserService userService = mock(UserService.class);
// Use the mock object
userService.createUser("john_doe");
// Verify that the createUser method was called with argument "john_doe"
verify(userService).createUser("john_doe");
}
}Common Mistakes and Tips
- Forgetting to Use
verify: Always useverifyto check interactions. - Incorrect Argument Matching: Ensure the arguments in
verifymatch exactly with the method call. - Overusing Verification: Verify only necessary interactions to keep tests maintainable.
Conclusion
In this section, we learned how to verify interactions with mocks using Mockito in JUnit. We covered basic verification, advanced verification techniques, and common mistakes. Verifying interactions is a powerful tool to ensure your code behaves as expected, especially when dealing with dependencies. In the next module, we will explore advanced JUnit features such as timeouts and exception testing.
JUnit Course
Module 1: Introduction to JUnit
Module 2: Basic JUnit Annotations
- Understanding @Test
- Using @Before and @After
- Using @BeforeClass and @AfterClass
- Ignoring Tests with @Ignore
Module 3: Assertions in JUnit
Module 4: Parameterized Tests
- Introduction to Parameterized Tests
- Creating Parameterized Tests
- Using @ParameterizedTest
- Custom Parameterized Tests
Module 5: Test Suites
Module 6: Mocking with JUnit
Module 7: Advanced JUnit Features
Module 8: Best Practices and Tips
- Writing Effective Tests
- Organizing Test Code
- Test-Driven Development (TDD)
- Continuous Integration with JUnit
