Mockito

Basic Mockito Usage

Maven Dependency

Maven

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>

<!-- Optional. Extension that initializes mocks and handles strict stubbings. -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>

If it is a spring project then include spring-boot-starter-test dependency. spring-boot-starter-test dependency already includes mockito-core and mockito-junit-jupiter dependency.

Basic Usage

Entity class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Item {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;

String name;

int price;
}

Repo class

1
2
3
4
5
6
@Repository
public interface ItemRepo extends JpaRepository<Item, Long> {

List<Item> findByName(String name);

}

Service class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class ItemService {
private final ItemRepo itemRepository;

@Autowired
public ItemService(ItemRepo itemRepository) {
this.itemRepository= itemRepository;
}

public Item findById(Long id) {
return itemRepository.findById(id).orElse(null);
}

public List<Item> findByName(String name) {
return itemRepository.findByName(name);
}
}

Unit test for Service class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import static org.mockito.Mockito.*;

import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class ItemServiceTest {
private ItemService itemService;
private ItemRepo itemRepo;

@BeforeEach
public void init() {
//create mock
itemRepo = mock(ItemRepo.class);

itemService = new ItemService(itemRepo);
}

@Test
public void testFindById() {
Item item = new Item();
item.setId(1L);
item.setName("MacBook");

// stubbing
when(itemRepo.findById(1L)).thenReturn(Optional.of(item));

// invoke method
Item itemFound = itemService.findById(1L);

// assertion
Assertions.assertEquals("MacBook", itemFound.getName() );

// verify
verify(itemRepo, times(1)).findById(1L);
}
}

use static import to import mockito methods

1
import static org.mockito.Mockito.*;

Mock is created by mock() method

Stubbing

Basic stubbing

1
when(itemRepo.findById(1L)).thenReturn(Optional.of(item));

Stubbing exception example test

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testFindById_error() {
Item item = new Item();
item.setId(1L);
item.setName("MacBook");

// stubbing Exception
when(itemRepo.findById(1L)).thenThrow(new RuntimeException("Some Exception"));

Assertions.assertThrows(RuntimeException.class, () -> itemService.findById(1L));
}

Stubbing exception for void return type method is different. We need to use doThrow() method because when() needs a return type.

1
2
3
List<String> mockList = mock(List.class);
doThrow(new RuntimeException("Some Exception")).when(mockList).add("123");
mockList.add("123");

Matchers

Mockito use equals method to match argument. If more flexibility is required, we can use matchers such as any(), anyInt(), anyLong(), anyString(), eq()…

1
2
3
4
when(itemRepo.findById(any())).thenReturn(Optional.of(item));

//verify using matcher
verify(itemRepo).findById(eq(1L));

If you are using argument matchers, all arguments have to be provided by matchers.

see ArgumentMatchers class for all matchers

Verify Number of invocations

You can verify the number of times a method is called. times(1) is the default.

1
2
3
4
5
6
7
8
9
10
verify(itemRepo).findByName("MacBook");

// verify a method is called twice
verify(itemRepo, times(2)).findByName("MacBook");

// verify a method is nver called
verify(itemRepo, never()).findByName("MacBook");

// verify a method is called at least once
verify(itemRepo, atLeastOnce()).findByName("MacBook");

Verify Invocation Order

use InOrder to verify invocation order.

1
2
3
4
5
6
7
8
// invoke methods
itemService.findById(1L);
itemService.findById(2L);

// verify Order
InOrder inOrder = inOrder(itemRepo);
inOrder.verify(itemRepo).findById(1L);
inOrder.verify(itemRepo).findById(2L);

Verify no more interactions

verifyNoMoreInteractions() - Verifies that no interactions happened on given mocks.

1
verifyNoMoreInteractions(mockObject);

Argument Captor

use ArgumentCaptor to capture argument values and further assertions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void testCaptor() {
Item item = new Item();
item.setId(1L);
item.setName("MacBook");

// stubbing
when(itemRepo.findByName("MacBook")).thenReturn(List.of(item));

// invoke method
itemService.findByName("MacBook");

// verify with argument captor
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(itemRepo).findByName(argument.capture());

// assert argument value
Assertions.assertEquals(argument.getValue(), "MacBook");
}

Annotation

@Mock

We can use @Mock annotation to create mock. This often results in more readable code.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ItemServiceTest {
@Mock
private ItemRepo itemRepo;

private ItemService itemService;

@BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
itemService = new ItemService(itemRepo);
}
// ...
}

MockitoAnnotations.openMocks(this) initializes fields annotated with Mockito annotations.

If using Junit5, then don’t need to execute MockitoAnnotations.openMocks(this), just annotate the test class with @ExtendWith(MockitoExtension.class)

1
2
3
4
5
6
7
8
9
10
11
12
13
@ExtendWith(MockitoExtension.class)
public class ItemServiceTest {
@Mock
private ItemRepo itemRepo;

private ItemService itemService;

@BeforeEach
public void setup() {
itemService = new ItemService(itemRepo);
}
// ...
}

@InjectMocks

@InjectMocks mark a field on which injection should be performed.

1
2
3
4
5
6
7
8
9
10
@ExtendWith(MockitoExtension.class)
public class ItemServiceTest {
@Mock
private ItemRepo itemRepo;

@InjectMocks
private ItemService itemService;

// ...
}

@Captor

With annotation enabled, we can also use @Captor annotation to create ArgumentCaptor.

1
2
@Captor
private ArgumentCaptor<String> argument;

Reference