There is a scenario to watch out for where we have class with a few instance variables of reference types but not all of them get initialized via a constructor. This post demonstrates shows how we could unknowingly miss initializing other mocks in a class and how to fix them.
Codes to Test with mocks
Without Constructor
[wp_ad_camp_1]
1 2 3 4 5 6 7 8 9 10 11 12 | public class SomeTask { private Service1 service1; private Service2 service2; public void execute() { service1.getDataById("001"); service2.getDataById("001"); } } |
Using @Mock
, and @InjectMocks
work fine as we would expect.
With Constructor
If we initialize one of the instance variables via a constructor, the other instance variable will not be.
[wp_ad_camp_2]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class SomeTask { private Service1 service1; private Service2 service2; /** * Comment out constructor if we want to * inject all mocks directly to fields * via @InjectMocks. * * @param service1 */ public SomeTask(Service1 service1) { this.service1 = service1; } public void execute() { service1.getDataById("001"); service2.getDataById("001"); } } |
Notice, service2
is null
.
How to fix it
There is no elegant way to fix. What we can do is explicitly initialized service2.
1 | MockitoAnnotations.initMocks(this); |
or
[wp_ad_camp_3]
1 2 | // Setter required someTask.setService2(service2); |
Example
Tested using 1.5.9.RELEASE
and Java 8
.
Download the codes
https://github.com/Turreta/com-turreta-mockito-injectmocks-constructors-and-fields
[wp_ad_camp_4]