How to mock List<Interface> while using @Mock and @InjectMock


Let's say you have a Service class which is holding, List of Handler. e.g. 

@Component
@RequiredArgsConstructor
public class Service {
private final List<Handler> handlerList;


Now, it's turn to write the test cases, using Junit5, and Mockito, you may be trying to write like this.

@ExtendWith(MockitoExtension.class)
class ServiceTest {

@InjectMocks
Service service;
@Mock
List<Handler> handlers;

 But mockito doesn't know anything about initialising the List. So putting @Mock is not going to work. 


There are 2 situations :- 

Scenario 1. 

You have setter method in the Service, for List<Handler> handlers;( assuming you haven't defined the List<Handler> as final)

in that case you can approach like this :- 

Define all the Handler implemented(which you want use in test) class and annotate with @Mock. 

Define instance of Service class(which you are going to test) and annotate with @InjectMock

Define handlers list. 

In beforeEach method, 

Initilize the List<Handler> with mocked classes. and set this List in Service class. 

@ExtendWith(MockitoExtension.class)
class ServiceTest {

@InjectMocks
Service service;

@Mock BaseHandler baseHandler;
@Mock SpecificHandler specificHandler;
List<Handler> handlers;

@BeforeEach
void setUp() {
handlers = List.of(baseHandler, specificHandler);
service.setHandlerList(handlers);
}


Scenario 2. 

You do not have setter method. 


In this class you can use @Spy

Define a ArrayList<Handler> handlers; 

and then add all mocked Handler to it.

these mocked instance of handler will be available in Service instance. 

@ExtendWith(MockitoExtension.class)
class ServiceTest {

@InjectMocks
Service service;

@Mock BaseHandler baseHandler;
@Mock SpecificHandler specificHandler;
@Spy
ArrayList<Handler> handlers;

@BeforeEach
void setUp() {
handlers.add(baseHandler);
handlers.add(specificHandler);

}

@Test
void shouldReturnBaseHandlerContent() {
when(baseHandler.accept()).thenReturn(true);
when(baseHandler.print()).thenReturn("Hey");
String text = service.print();
assertEquals(text, "Hey");
}

}

Please note you need to define concrete class(ArrayList) not interface List for spying. 


Happy Mocking. 


Comments