I had this:
@Mock
MessageSource mockMessageSource;
@InjectMocks
PhoneNumberUtil phoneNumberUtil;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");
}
Where
public PhoneNumberUtil(MessageSource messageSource) {
this.firstValue = messageSource.getMessage("first.key"), null, FIRST_DEFAULT_VALUE, Locale.getDefault());
this.secondValue = messageSource.getMessage("second.key"), null, SECOND_DEFAULT_VALUE, Locale.getDefault());
}
I was running my unit test but wondering why the fields "firstValue" and "secondValue" were still coming out as null.
I already mocked the messageSource.getMessage() calls. Why weren't my mocks getting called??
Then I realised: the when().thenReturn() calls weren't getting called until AFTER PhoneNumberUtil was already initialized!
I was using @InjectMocks and once the line
MockitoAnnotations.initMocks(this);
was called, phoneNumberUtil would already get initialised with mockMessageSource. But at that point, mockMessageSource isn't setup to do anything yet.
So the fix was to do this in my setup()
@Mock
MessageSource mockMessageSource;
PhoneNumberUtil phoneNumberUtil;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");
phoneNumberUtil = new PhoneNumberUtil(mockMessageSource);
}
If you need to make a call on a mocked dependency in the constructor of the class you're testing, then you can't use the @InjectMocks pattern.
You need to create the class you are testing using code, not annotations, using constructor injection to pass in the mocked dependencies, and you need to create it after you've mocked the methods being called in the constructor.