@InjectMocks doesn’t work to test a class with Constructor Injection.
Lets see the class to test:
@Component
public class MyService {
private final MyDependency myFirstDependency;
private final MyDependency mySecondDependency;
MyService(@Qualifier("MyFirstDependencyBean") final MyDependency myFirstDependency,
@Qualifier("MySecondDependencyBean") final MyDependency mySecondDependency){
this.myFirstDependency = myFirstDependency;
this.mySecondDependency = mySecondDependency;
}
public String myOperation(){
if(myFirstDependency.toString().contains("First")){
System.out.println("First Bean available");
return "First";
}
if(mySecondDependency.toString().contains("Second")){
System.out.println("Second Bean available");
return "Second";
}
return "None";
}
}
Junit that will fail with @InjectMocks is provided below. The Junits will fail randomly and Mockito when will not be applied properly.
@RunWith(SpringRunner.class)
public class MyServiceTest {
@Mock
private MyDependency myFirstDependency;
@Mock
private MyDependency mySecondDependency;
@InjectMocks
MyService myService;
@Test
public void testMyOperationFirstBean(){
Mockito.when(myFirstDependency.toString()).thenReturn("First");
Assert.assertEquals("First", myService.myOperation());
}
@Test
public void testMyOperationSecondBean(){
Mockito.when(myFirstDependency.toString()).thenReturn("Second");
Mockito.when(mySecondDependency.toString()).thenReturn("Second");
Assert.assertEquals("Second", myService.myOperation());
}
}
Fix:
The fix is to not use @InjectMocks but to use the myService Constructor as shown below.
MyService myService;
@Before
public void Setup(){
myService = new MyService(myFirstDependency, mySecondDependency);
}
The full Junit class is provided below.
@RunWith(SpringRunner.class)
public class MyServiceTest {
@Mock
private MyDependency myFirstDependency;
@Mock
private MyDependency mySecondDependency;
MyService myService;
@Before
public void Setup(){
myService = new MyService(myFirstDependency, mySecondDependency);
}
@Test
public void testMyOperationFirstBean(){
Mockito.when(myFirstDependency.toString()).thenReturn("First");
Assert.assertEquals("First", myService.myOperation());
}
@Test
public void testMyOperationSecondBean(){
Mockito.when(myFirstDependency.toString()).thenReturn("Second");
Mockito.when(mySecondDependency.toString()).thenReturn("Second");
Assert.assertEquals("Second", myService.myOperation());
}
}