Mockito times()

Introduction

The times() method in Mockito is used to specify the number of times a method should be called on a mock object. This is useful for verifying that certain interactions happened a specific number of times. This tutorial will demonstrate how to use the times() method in Mockito to check the number of method invocations.

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 MessageService class that has a dependency on a MessageRepository. Our goal is to test the MessageService methods using the times() method in Mockito to check the number of interactions with the MessageRepository.

MessageService and MessageRepository Classes

First, create the Message class, the MessageRepository interface, and the MessageService class.

public class Message {
    private String content;

    // Constructor, getters, and setters
    public Message(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

public interface MessageRepository {
    void saveMessage(Message message);
    int getMessageCount();
}

public class MessageService {
    private final MessageRepository messageRepository;

    public MessageService(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }

    public void sendMessage(String content) {
        Message message = new Message(content);
        messageRepository.saveMessage(message);
    }

    public int retrieveMessageCount() {
        return messageRepository.getMessageCount();
    }
}

JUnit 5 Test Class with Mockito

Create a test class for MessageService 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 MessageServiceTest {

    @Mock
    private MessageRepository messageRepository;

    @InjectMocks
    private MessageService messageService;

    @Test
    public void testSendMessage() {
        // Given
        String content = "Hello, World!";

        // When
        messageService.sendMessage(content);

        // Then
        verify(messageRepository, times(1)).saveMessage(new Message(content));
    }

    @Test
    public void testSendMessageMultipleTimes() {
        // Given
        String content = "Hello, World!";

        // When
        messageService.sendMessage(content);
        messageService.sendMessage(content);

        // Then
        verify(messageRepository, times(2)).saveMessage(new Message(content));
    }

    @Test
    public void testRetrieveMessageCount() {
        // Given
        when(messageRepository.getMessageCount()).thenReturn(5);

        // When
        int count = messageService.retrieveMessageCount();

        // Then
        assertEquals(5, count);
        verify(messageRepository, times(1)).getMessageCount();
    }
}

Explanation

  1. The @Mock annotation creates a mock instance of the MessageRepository interface. This mock instance can be used to simulate the behavior of the MessageRepository in a controlled way.
  2. The @InjectMocks annotation injects the mock MessageRepository into the MessageService instance to provide a controlled test environment. This allows the MessageService methods to be tested in isolation from the actual MessageRepository implementation.
  3. The verify(messageRepository, times(1)).saveMessage(new Message(content)); method checks if the saveMessage method was called exactly once on the MessageRepository with the expected Message object. This ensures that the sendMessage method of the MessageService class interacts with the MessageRepository correctly.
  4. The verify(messageRepository, times(2)).saveMessage(new Message(content)); method checks if the saveMessage method was called exactly twice on the MessageRepository with the expected Message object. This ensures that the sendMessage method of the MessageService class interacts with the MessageRepository the expected number of times.
  5. The verify(messageRepository, times(1)).getMessageCount(); method checks if the getMessageCount method was called exactly once on the MessageRepository. This ensures that the retrieveMessageCount method of the MessageService class interacts with the MessageRepository correctly.

Additional Scenarios

Scenario: Verifying No Interactions

In this scenario, we will demonstrate how to verify that no interactions occurred with the mock object using the verifyNoInteractions() method.

@Test
public void testNoInteractionsWithRepository() {
    // Given
    // No interactions expected

    // When
    // No method calls

    // Then
    verifyNoInteractions(messageRepository);
}

Scenario: Verifying Never Called

In this scenario, we will demonstrate how to verify that a method was never called using the times(0) method.

@Test
public void testSendMessageNeverCalled() {
    // Given
    String content = "Hello, World!";

    // When
    // No sendMessage call

    // Then
    verify(messageRepository, times(0)).saveMessage(new Message(content));
}

Conclusion

The times() method in Mockito simplifies the verification of method call counts on mock objects for unit testing. By using times(), you can easily check if certain methods were called the expected number of times, ensuring that the code under test interacts with its dependencies as expected. This step-by-step guide demonstrated how to effectively use the times() method in your unit tests, covering different scenarios to ensure comprehensive testing of the MessageService class.

Related Mockito Methods

Mockito mock()
Mockito spy()
Mockito when()
Mockito thenThrow()
Mockito verify()
Mockito times()
Mockito never()
Mockito any()
Mockito eq()
Mockito inOrder()
Mockito doReturn()
Mockito doThrow()
Mockito doAnswer()
Mockito timeout()
Mockito ArgumentMatchers

Comments