W3docs

Java Mocking with Mockito

Mock dependencies in Java tests with Mockito — mock, when/thenReturn, verify, and argument captors.

Java Mocking with Mockito

A unit test should exercise one class in isolation. But real classes lean on collaborators — a database, a payment gateway, an email sender — that are slow, unreliable, or have side effects you do not want in a test. Mockito is the most widely used Java library for replacing those collaborators with mocks: stand-in objects you program to return canned answers and then interrogate about how they were called. This chapter shows the Mockito API you will write every day, and proves the underlying idea with a plain-JDK program you can run right here.

Why mock at all

The class under test (the system under test, or SUT) usually receives its collaborators through its constructor — that is what dependency injection buys you. In a test you hand it a fake collaborator instead of the real one. A good fake does two jobs:

  • Stubbing — it returns whatever value the test scenario needs (charge(...) returns true, or throws), so you can drive the SUT down a specific path without a real network call.
  • Verification — it records every call it received, so afterwards the test can assert the SUT called it the right way, the right number of times, with the right arguments.

Mockito generates such a fake for any interface or non-final class at runtime, so you never hand-write one. But knowing what it generates makes the API obvious.

Creating mocks and stubbing returns

Mockito.mock(Type.class) produces a mock. By default every method returns a "nice" empty value — null for objects, false for booleans, 0 for numbers. You then override the methods you care about with when(...).thenReturn(...).

import static org.mockito.Mockito.*;

PaymentGateway gateway = mock(PaymentGateway.class);

// Stub: when charge is called with these args, return true.
when(gateway.charge("acct-7", 1999)).thenReturn(true);

// Stub a method to throw, to test error handling.
when(gateway.charge("acct-x", 1)).thenThrow(new GatewayException("down"));

For void methods the order flips: doThrow(...).when(mock).method(). Stubs can also be loosened with argument matchers like anyString() and anyInt() so they fire for any call, not just one exact set of arguments.

Verifying interactions

After the SUT runs, verify(...) asserts how the mock was used. This is how you test side effects — an email that should have been sent, a row that should have been saved — without inspecting the real system.

verify(gateway).charge("acct-7", 1999);        // called exactly once (default)
verify(gateway, times(2)).charge(anyString(), anyInt());
verify(gateway, never()).refund(anyString());  // must NOT have been called
verifyNoMoreInteractions(gateway);             // nothing else happened

The common verification modes:

ModeMeaning
times(n)Called exactly n times
never()Same as times(0)
atLeastOnce() / atLeast(n)Called at least once / n times
atMost(n)Called no more than n times
only()This was the only method called on the mock

Capturing arguments

When you need to inspect what was passed — not just that a call happened — use an ArgumentCaptor. It grabs the actual argument so you can assert on its fields, which is invaluable when the SUT builds an object before passing it on.

ArgumentCaptor<Order> captor = ArgumentCaptor.forClass(Order.class);
verify(repository).save(captor.capture());

Order saved = captor.getValue();
assertEquals("acct-7", saved.account());
assertEquals(1999, saved.amountCents());

@Mock, @InjectMocks, and spies

In real test classes you rarely call mock() by hand. The annotations wire everything up: @Mock declares a mock field, @InjectMocks builds the SUT and pushes the mocks into its constructor, and @ExtendWith(MockitoExtension.class) (JUnit 5) activates the processing.

@ExtendWith(MockitoExtension.class)
class CheckoutServiceTest {
  @Mock PaymentGateway gateway;
  @InjectMocks CheckoutService service;   // gets the mock injected

  @Test
  void paysWhenGatewayApproves() {
    when(gateway.charge("acct-7", 1999)).thenReturn(true);
    assertEquals("PAID", service.checkout("acct-7", 1999));
    verify(gateway).charge("acct-7", 1999);
  }
}

A spy (spy(realObject)) is the middle ground: it wraps a real object and runs real methods unless you stub them — handy for partial mocking of legacy code.

A worked example: a hand-built mock

Mockito itself is not on this page's classpath, so the runnable program below builds the mock by hand — a small class implementing the dependency interface that holds a stubbed return value and records every call. This is precisely the machinery Mockito generates for you at runtime, so reading it tells you exactly what when/thenReturn and verify do under the hood.

java— editable, runs on the server

What to take from the run:

  • The MockGateway's stubbedResult = true is the hand-written form of when(gateway.charge(...)).thenReturn(true); because the stub returned true, the SUT printed result : PAID without any real payment ever happening.
  • invocationCount == 1 printing true is exactly what verify(gateway).charge(...) checks — the mock counted that it was called once, which is how Mockito turns "did this interaction occur?" into a pass/fail assertion.
  • The calls list captured charge(acct-7, 1999), the argument-capture idea behind ArgumentCaptor: a mock remembers not just that it was called but with what, so the test can assert on the actual arguments.
  • Re-creating the mock with stubbedResult = false drove the SUT down its other branch and printed declined result : DECLINED, showing how one fake lets you script every scenario the real collaborator could produce.
  • The guard clause returned INVALID before reaching the gateway, so invocationCount == 0 printed true — the runnable proof of verify(gateway, never()).charge(...), asserting a dependency was deliberately not touched.

Practice

Practice

In a Mockito-based unit test, what is the purpose of a call like verify(gateway, never()).charge(anyString(), anyInt())?