Cheat Sheet · Mockito 5.x · JUnit 5
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <scope>test</scope> </dependency>
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
UserRepository userRepo; // Fake dependency
@InjectMocks
UserService userService; // Class under test
// OR: manual init (non-annotation)
AutoCloseable closeable;
@BeforeEach void init() {
closeable = MockitoAnnotations.openMocks(this);
}
@AfterEach void tearDown() throws Exception {
closeable.close();
}
}@MockBean UserRepository userRepo; // Replaces Spring bean @Autowired UserService userService; // Real Spring bean
@ExtendWith(MockitoExtension.class)
class MyTest { ... }@Mock UserRepository userRepo;
@InjectMocks UserService userService;
@Spy List<String> spyList = new ArrayList<>();
@Captor ArgumentCaptor<String> captor;
@DoNotMock(reason = "Use FakePaymentGateway")
interface PaymentGateway { ... }@MockBean EmailService emailService;
when(userRepo.findById("1")).thenReturn(Optional.of(user));
// Sequence — last value repeats forever
when(mock.next()).thenReturn("a", "b", "c"); // a, b, c, c, c…
// Chaining
when(mock.get()).thenReturn("first").thenReturn("second");
// Unstubbed methods → null / 0 / false (defaults)when(userRepo.findById(anyString()))
.thenThrow(new RuntimeException("DB down"));
// By class (Mockito instantiates)
when(listMock.add(anyString()))
.thenThrow(IllegalStateException.class);
// Return then throw
when(mock.next()).thenReturn("a").thenThrow(RuntimeException.class);// Inline lambda
when(repo.findUser(anyString()))
.thenAnswer(invocation -> {
String arg = invocation.getArgument(0);
return new User(arg);
});
// Reusable Answer class
class CustomAnswer implements Answer<Boolean> {
@Override
public Boolean answer(InvocationOnMock inv) {
return false;
}
}
// All unstubbed methods use this answer:
MyList mock = mock(MyList.class, new CustomAnswer());// when() can't wrap void — use doX().when() form
doThrow(RuntimeException.class).when(service).sendEmail(any());
doNothing().when(service).sendEmail(any());
doCallRealMethod().when(service).sendEmail(any());
// Complex void with doAnswer
doAnswer(invocation -> {
String to = invocation.getArgument(0);
String subject = invocation.getArgument(1);
assertEquals("alice@test.com", to);
return null; // void must return null
}).when(emailService).send(anyString(), anyString());when(listMock.size()).thenCallRealMethod();
import static org.mockito.BDDMockito.*;
// given() == when() — same logic, better grammar
given(userRepo.findById("1")).willReturn(Optional.of(user));
given(userRepo.save(any())).willThrow(DataException.class);
// Void BDD stubbing
willDoNothing().given(service).archive(any());
willThrow(new RuntimeException()).given(service).archive(null);any() // any object including null any(User.class) // any non-null User instance anyString() // any non-null String anyInt() // any int / anyLong() / anyDouble() anyBoolean() // any boolean anyList() // any List / anyMap() / anyCollection() isNull() // must be null isNotNull() // must not be null
eq("specificValue") // exact value (use when mixing matchers)
eq(42) // primitive exact match
same(object) // same reference (==)
contains("substring")
startsWith("prefix")
endsWith("suffix")
matches("regex.*")// Lambda predicate in stub
when(repo.save(argThat(user -> user.getAge() > 18)))
.thenReturn(savedUser);
// Lambda predicate in verify
verify(repo).save(argThat(u ->
u.getEmail().endsWith("@company.com")));// WRONG — raw value mixed with matcher
when(mock.update("id", any(User.class))); // throws
// CORRECT — all args must be matchers
when(mock.update(eq("id"), any(User.class)));// Basic UserRepo repo = mock(UserRepo.class); // With debug name (appears in failure messages) UserRepo repo = mock(UserRepo.class, "userRepoMock"); // With default answer strategy UserRepo repo = mock(UserRepo.class, RETURNS_DEEP_STUBS); // mock.getAddress().getCity() — each link returns a mock // Other defaults: RETURNS_SMART_NULLS, CALLS_REAL_METHODS
verify(userRepo).findById("1"); // called exactly once
verify(userRepo, times(3)).findAll(); // exactly 3 times
verify(userRepo, atLeast(1)).save(any());
verify(userRepo, atLeastOnce()).save(any());
verify(userRepo, atMost(5)).save(any());
verify(userRepo, never()).deleteAll(); // never calledverifyNoInteractions(userRepo); // zero calls total verifyNoMoreInteractions(userRepo); // no calls beyond verified // Call after all verify() for strict interaction checking
InOrder inOrder = inOrder(repoMock, emailMock); // Verify this exact sequence: inOrder.verify(repoMock).save(any()); inOrder.verify(emailMock).send(anyString()); // Ignores other calls between verified steps
verify(userRepo).save(any(User.class));
verify(userRepo).findById(eq("abc-123"));
verify(userRepo, times(2)).findByEmail(anyString());// Polls until condition satisfied or timeout verify(asyncService, timeout(500)).processJob(); verify(asyncService, timeout(1000).times(2)).processJob();
then(userRepo).should().save(any()); then(userRepo).should(times(2)).findAll(); then(userRepo).shouldHaveNoInteractions(); then(userRepo).shouldHaveNoMoreInteractions();
@Spy
List<String> spyList = new ArrayList<>();
@Test void testSpy() {
spyList.add("item1"); // real method runs
spyList.add("item2");
verify(spyList, times(2)).add(anyString());
assertEquals(2, spyList.size()); // real size
}
// Stub a spy method — use doReturn, NOT when()
doReturn(100).when(spyList).size();
// when(spyList.size()) would invoke real method first!
// Programmatic
List<String> spy = spy(new ArrayList<>());@Mock DependencyService dep;
UserService spyService;
@BeforeEach void setUp() {
// Create spy manually — pass mock via constructor
spyService = spy(new UserService(dep));
}@Captor ArgumentCaptor<User> userCaptor;
@Captor ArgumentCaptor<String> emailCaptor;
@Test void testCaptor() {
userService.createUser("alice", "alice@test.com");
verify(userRepo).save(userCaptor.capture());
User saved = userCaptor.getValue();
assertEquals("alice", saved.getUsername());
verify(emailService).send(emailCaptor.capture());
assertThat(emailCaptor.getValue()).contains("alice@test.com");
}
// Capture multiple calls
verify(mock, times(3)).add(captor.capture());
List<String> all = captor.getAllValues(); // ["a","b","c"]// Scoped try-with-resources — original restored on close
try (MockedStatic<Utils> mockedUtils = mockStatic(Utils.class)) {
mockedUtils.when(() -> Utils.generateId())
.thenReturn("test-id");
mockedUtils.when(() -> Utils.format(anyString()))
.thenReturn("formatted");
String result = service.createUser("alice");
mockedUtils.verify(() -> Utils.generateId(), times(1));
assertEquals("test-id-alice", result);
}
// Outside block — real static method restoredtry (MockedConstruction<PaymentGateway> mocked =
mockConstruction(PaymentGateway.class, (mock, ctx) -> {
when(mock.charge(anyDouble())).thenReturn(true);
})) {
// Any new PaymentGateway() inside block returns mock
OrderService service = new OrderService();
service.placeOrder(100.0);
verify(mocked.constructed().get(0)).charge(100.0);
}// NPE without deep stubs — getAddress() returns null
User user = mock(User.class, RETURNS_DEEP_STUBS);
when(user.getAddress().getCity()).thenReturn("Hyderabad");
// ⚠ Signals Law of Demeter violation — fix design insteadUserRepo repo = mock(UserRepo.class,
withSettings()
.name("userRepoMock")
.defaultAnswer(RETURNS_SMART_NULLS)
.extraInterfaces(Serializable.class)
.verboseLogging()
);// mock() doesn't initialize instance vars
// spy() copies instance state — more realistic
Greeter spy = spy(new Greeter("Hello"));
doCallRealMethod().when(spy).greet(anyString());given() is identical to when() internally. Purely semantic — keeps the test narrative readable.import static org.mockito.BDDMockito.*;
@Test void shouldSendEmailOnUserCreation() {
// Given
given(userRepo.save(any(User.class)))
.willReturn(savedUser);
given(emailService.isAvailable()).willReturn(true);
// When
userService.createUser("alice", "alice@test.com");
// Then
then(emailService).should(times(1))
.send(eq("alice@test.com"), anyString());
then(userRepo).should().save(any(User.class));
then(auditLog).shouldHaveNoInteractions();
}
// BDD void stubbing
willDoNothing().given(service).archive(any());
willThrow(RuntimeException.class).given(service).archive(null);thenReturn(val)Return a valuethenReturn(a,b,c)Return sequence (last repeats)thenThrow(Ex.class)Throw exceptionthenAnswer(inv->)Dynamic / computed answerthenCallRealMethod()Delegate to real impldoReturn(val)Stub without calling real (spy)doThrow(ex)Throw on void methoddoNothing()Suppress void (default)doAnswer(inv->)Complex void behaviordoCallRealMethod()Delegate to real impltimes(n)Exactly n invocationsnever()Zero invocationsatLeastOnce()One or moreatLeast(n)n or moreatMost(n)n or fewertimeout(ms)Within timeout (async)only()This call and nothing elseany()Any object (incl. null)any(T.class)Any non-null TanyString()Any non-null StringanyInt/Long/…()Primitive type matcherseq(val)Exact value (needed when mixing)argThat(pred)Custom predicate lambdacontains/matches()String matchersisNull() / isNotNull()Null checksMockitoMain API entry pointBDDMockitogiven / then BDD APIInOrderSequential verifyArgumentCaptor<T>Capture call argumentsInvocationOnMockAccess args in thenAnswerMockedStatic<T>Scoped static mockMockedConstruction<T>Scoped constructor mockMockSettingsAdvanced mock configRETURNS_DEFAULTSnull / 0 / false (standard)RETURNS_SMART_NULLSSmartNull — better NPE messagesRETURNS_DEEP_STUBSChain mocks (avoid)CALLS_REAL_METHODSLike a spy on the classRETURNS_MOCKSReturns mocks for everythingUnnecessaryStubbingExceptionStubbed but never called in testWantedButNotInvokedverify() not satisfiedTooManyActualInvocationstimes(n) exceededInvalidUseOfMatchersExceptionMixed raw + matcher args