🧪

Mockito

Cheat Sheet · Mockito 5.x · JUnit 5

mockstubspyverifycaptorstatic
Setup & Basics
Dependencies (pom.xml)
<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>

Class Setup
@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();
  }
}

Spring Variant
@MockBean UserRepository userRepo;  // Replaces Spring bean
@Autowired UserService userService; // Real Spring bean

Test Doubles
DummyPassed around but never used. Fills parameter slots.
FakeWorking impl with shortcuts (e.g. in-memory DB).
StubReturns predefined responses. when().thenReturn().
MockVerifies interactions. Smarter stubs. verify().
SpyWraps real object. Records how methods were called.

Stub
Isolate dependency. Provide controlled output. Focus on logic under test.
Mock
Verify interactions — was method called? How many times? With what args?
Annotations
@ExtendWith(MockitoExtension.class)
Required on class. Activates all Mockito annotations in JUnit 5.
@ExtendWith(MockitoExtension.class)
class MyTest { ... }
@Mock
Creates a full mock. All methods return defaults (null/0/false) unless stubbed. Only works on Mocks and Spies.
@Mock UserRepository userRepo;
@InjectMocks
Instantiates class under test and injects @Mock / @Spy fields via constructor, setter, or field injection.
@InjectMocks UserService userService;
@Spy
Wraps a real object. Real methods called unless stubbed. Use doReturn() not when() to avoid calling real method during stub setup.
@Spy List<String> spyList = new ArrayList<>();
@Captor
Creates ArgumentCaptor. Captures arguments passed to a mock for later assertion.
@Captor ArgumentCaptor<String> captor;
@DoNotMock
Applied at class/interface level. Signals this type should never be mocked — use a real impl or fake instead.
@DoNotMock(reason = "Use FakePaymentGateway")
interface PaymentGateway { ... }
@MockBean / @SpyBean
Spring Boot only. Registers mock/spy as Spring bean, replacing existing bean in the application context.
@MockBean EmailService emailService;
Stubbing — when / then
Return Values
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)

Throw Exceptions
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);

Dynamic Answer
// 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());

Void Methods — use do* prefix
// 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());

Call Real Method on Mock
when(listMock.size()).thenCallRealMethod();

BDD Style (given / will)
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);
Argument Matchers
⚠ If any argument uses a matcher, ALL arguments must use matchers.
Type Matchers
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

Value & String Matchers
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.*")

Custom Matcher (argThat)
// 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")));

Mixing — eq() required
// 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)));

Programmatic mock()
// 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
Basic Invocation
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 called

No Interactions
verifyNoInteractions(userRepo);       // zero calls total
verifyNoMoreInteractions(userRepo);  // no calls beyond verified
// Call after all verify() for strict interaction checking

Ordered Verification
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 with Matchers
verify(userRepo).save(any(User.class));
verify(userRepo).findById(eq("abc-123"));
verify(userRepo, times(2)).findByEmail(anyString());

Async / Timeout
// Polls until condition satisfied or timeout
verify(asyncService, timeout(500)).processJob();
verify(asyncService, timeout(1000).times(2)).processJob();

BDD Verify (then / should)
then(userRepo).should().save(any());
then(userRepo).should(times(2)).findAll();
then(userRepo).shouldHaveNoInteractions();
then(userRepo).shouldHaveNoMoreInteractions();

💡 Verify behavior, not implementation
Only verify interactions that matter for the test outcome. Over-verifying makes tests fragile.
Spy & Argument Captor
Spy — partial mock of real object
@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
All methods → defaults. No real code runs. list.add("x") → false, list stays empty.
Spy
Real methods called unless overridden. list.add("x") actually adds to list.
Injecting Mock into Spy
@Mock DependencyService dep;
UserService spyService;

@BeforeEach void setUp() {
    // Create spy manually — pass mock via constructor
    spyService = spy(new UserService(dep));
}

ArgumentCaptor — capture internal args
Use when the argument is built inside the method under test and not accessible from the test.
@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"]
⚠ Avoid ArgumentCaptor in stubbing (when clauses) — reduces readability. Use argThat() in stubs. Captor belongs with verify().
Static, Void & Advanced Mocking
Static Methods
// 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 restored
⚠ Private static methods cannot be mocked. Wrap static logic in an injectable non-static class instead.

Mocking Constructors (new)
try (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);
}

Deep Stubs
// 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 instead

MockSettings (advanced config)
UserRepo repo = mock(UserRepo.class,
    withSettings()
        .name("userRepoMock")
        .defaultAnswer(RETURNS_SMART_NULLS)
        .extraInterfaces(Serializable.class)
        .verboseLogging()
);

Spy from void — use spy not mock
// mock() doesn't initialize instance vars
// spy() copies instance state — more realistic
Greeter spy = spy(new Greeter("Hello"));
doCallRealMethod().when(spy).greet(anyString());
BDD Style — given / when / then
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);
Best Practices
Verify behavior, not implementation details
One logical assertion per test (AAA / BDD)
Use ArgumentCaptor for args created internally
Prefer BDD style (given/when/then) for readability
Fresh mocks per test — rely on @BeforeEach
thenCallRealMethod() sparingly — prefer real classes
Avoid reset() — hides test design issues
Don't mock value objects or DTOs
Don't mock types you don't own — use wrappers
Avoid ArgumentCaptor inside when() stubs
Avoid RETURNS_DEEP_STUBS — fix design instead
Don't over-verify — only what matters to outcome
Quick Reference
when().then*
thenReturn(val)Return a value
thenReturn(a,b,c)Return sequence (last repeats)
thenThrow(Ex.class)Throw exception
thenAnswer(inv->)Dynamic / computed answer
thenCallRealMethod()Delegate to real impl
do*().when() — voids
doReturn(val)Stub without calling real (spy)
doThrow(ex)Throw on void method
doNothing()Suppress void (default)
doAnswer(inv->)Complex void behavior
doCallRealMethod()Delegate to real impl
verify() modes
times(n)Exactly n invocations
never()Zero invocations
atLeastOnce()One or more
atLeast(n)n or more
atMost(n)n or fewer
timeout(ms)Within timeout (async)
only()This call and nothing else
Argument Matchers
any()Any object (incl. null)
any(T.class)Any non-null T
anyString()Any non-null String
anyInt/Long/…()Primitive type matchers
eq(val)Exact value (needed when mixing)
argThat(pred)Custom predicate lambda
contains/matches()String matchers
isNull() / isNotNull()Null checks
Key Classes
MockitoMain API entry point
BDDMockitogiven / then BDD API
InOrderSequential verify
ArgumentCaptor<T>Capture call arguments
InvocationOnMockAccess args in thenAnswer
MockedStatic<T>Scoped static mock
MockedConstruction<T>Scoped constructor mock
MockSettingsAdvanced mock config
Default Answers
RETURNS_DEFAULTSnull / 0 / false (standard)
RETURNS_SMART_NULLSSmartNull — better NPE messages
RETURNS_DEEP_STUBSChain mocks (avoid)
CALLS_REAL_METHODSLike a spy on the class
RETURNS_MOCKSReturns mocks for everything

Common Exceptions
UnnecessaryStubbingExceptionStubbed but never called in test
WantedButNotInvokedverify() not satisfied
TooManyActualInvocationstimes(n) exceeded
InvalidUseOfMatchersExceptionMixed raw + matcher args
Mockito 5.x · JUnit 5 · mockito-junit-jupiter · Java 17+