Direct invocations on mocks should be avoided in tests.
When you call a method on a mock, the call normally does only what you have
configured it to do (through calls to when(...).thenReturn/thenAnswer
, etc.)
and makes a record of the call that can be read by later verify(...)
calls.
Both of these are rarely what you want:
verify(foo).bar()
, then the
reader will expect the test to succeed only because the code under test
called bar()
, not because the test itself did.Sometimes, test authors, especially those familiar with other mocking frameworks (like EasyMock), will call a method on a mock for one of two reasons:
verify(foo).bar()
, and it must do so after the code under test has run.@Test
public void balanceIsChecked() {
Account account = mock(Account.class);
LoanChecker loanChecker = new LoanChecker(account);
assertThat(loanChecker.checkEligibility()).isFalse();
// Should be verify(account).checkBalance();, or be removed if the call to
// `checkEligibility` is sufficient proof the code is behaving as intended.
account.checkBalance();
}
There is at least one edge case in which a call to a mock has different effects:
A call to a final
method will normally not be intercepted by Mockito, so it
will run the implementation of that method in the code under test. Sometimes,
that method will call other methods on the mock object, producing effects
similar to if the test had called those methods directly. Sometimes, the method
will have other effects. Both kinds of effects can be confusing, so prefer to
avoid such calls when possible.
Suppress false positives by adding the suppression annotation @SuppressWarnings("DirectInvocationOnMock")
to the enclosing element.