Mocking with Mockito in Java
Mocks vs stubs vs fakes, when/thenReturn, verify, not mocking what you don't own.
Meet the doubles
A test double stands in for a real dependency. A stub returns canned answers. A mock records calls so you can verify them. A fake is a simple working version, like an in-memory repository. A spy wraps a real object and overrides some calls.
Script it, then check it
Mockito creates doubles with **mock(). when(...).thenReturn(...) scripts answers; verify(...)** checks what was called.
UserRepo repo = mock(UserRepo.class);
when(repo.findName(1)).thenReturn("Ana");
var greeter = new Greeter(repo);
assertEquals("Hi Ana", greeter.greet(1));
verify(repo).findName(1);Nothing stubbed
repo is a mock and nothing is stubbed. What does repo.findAll() (returning List<User>) return?
An empty listnullThrows UnsupportedOperationException
Show the answer
An empty list. Unstubbed methods return harmless defaults: empty collections, empty Optionals, 0, false, or null for other objects. So tests only stub what matters to them.
Matchers are all or nothing
Once one argument uses a matcher like anyString(), every argument must be a matcher. The raw 3 makes Mockito throw InvalidUseOfMatchersException. Write **eq(3)** instead.
when(pricing.quote(anyString(), 3)) // bad
.thenReturn(99.0);
when(pricing.quote(anyString(), eq(3))) // ok
.thenReturn(99.0);Verifying counts
verify runs after the code under test and checks interactions. **times(n)** asserts an exact count; never() and atLeastOnce() exist too. when() only sets up answers; it checks nothing.
checkout.placeOrder(order);
verify(mailer, times(1)).send(any());
verify(audit, never()).alert(any());Don't mock what you don't own
HttpClient http = mock(HttpClient.class);
when(http.send(any(), any()))
.thenReturn(fakeResponse);Encodes your guesses about a foreign API's behavior.
PaymentGateway gw = mock(PaymentGateway.class);
when(gw.charge(order)).thenReturn(OK);Your own small interface; test the real wrapper with integration tests.
Over-mocking
A suite where everything is mocked can be green while production is on fire: the mocks agree with your assumptions, not with reality. Mock at boundaries you own (payments, mail, clock), keep real objects inside, and back the boundaries with a few integration tests.
Key takeaways
- Stub = canned answers; mock = verify interactions; fake = simple real version
- If one argument uses a matcher, all of them must
- verify(mock, times(n)).method(...) checks calls
- Don't mock what you don't own: wrap it first
Mockito builds its mocks at runtime with the ByteBuddy bytecode library, generating classes on the fly, much like frameworks do for class-based proxies.
Practice questions
repo is a Mockito mock and nothing is stubbed. What does `repo.findAll()` (returning List<User>) return?
- Throws UnsupportedOperationException
- A list with one mock User
- null
- An empty list
Check your answer
An empty list. Mockito's default answer returns empty collections, empty Optionals, 0, false or null, so unstubbed calls rarely crash a test.
You must check that exactly one email is sent when an order is placed. Which Mockito call fits?
- mock(Mailer.class, times(1))
- when(mailer.send(any())).thenReturn(true)
- verify(mailer, times(1)).send(any())
- assertEquals(1, mailer)
Check your answer
verify(mailer, times(1)).send(any()). verify checks interactions after the code has run; times(1) asserts the exact count. Stubbing with when() only sets up answers.