skip to content

What is a mock object in Mockito, how do you create one, and why would you use it in a unit test?

level: juniorimportance: must knowfreq 85%

answer

  1. mock(Class) returns a fake of that type
  2. @Mock == mock(SomeClass.class)
  3. isolate the SUT from real collaborators
  4. unstubbed mock returns null/0/false/empty
  5. works for interfaces and classes (ByteBuddy)

basics

~20 s

A mock is a fake stand-in for a real object that you create with Mockito.mock(SomeClass.class). You use it to replace a real collaborator so your test exercises only the one class you care about, without its dependencies doing real work.

solid answer

~50 s

A mock is an automatically generated test double that implements the interface or extends the class you pass to Mockito.mock(SomeClass.class). It records the calls made to it and lets you program its return values (with when/thenReturn) and verify interactions. The point is isolation: the class under test usually depends on collaborators (a database repository, an HTTP client, a service). In a true unit test you do not want those collaborators doing real work, because that is slow, non-deterministic, and tests other code. So you swap each collaborator for a mock, hand the mocks to the class under test, and now the test depends only on that one class plus the controlled behaviour you scripted on the mocks. You create mocks either programmatically with Mockito.mock(Class) or declaratively with the @Mock annotation. A mock you have not stubbed returns harmless defaults (null, 0, false, empty collections), so it will not throw on its own.

go deeper

for a junior

Can create a mock with mock(Class) or @Mock and explain it replaces a real collaborator so the test only exercises the SUT.

for a middle

Knows @Mock needs MockitoExtension/openMocks, knows mock vs spy, and articulates isolation/determinism as the motivation.

for a senior

Discusses when mocking is appropriate vs. a fake, the cost of over-mocking (tests coupled to implementation), and how default answers avoid NPEs.

for a principal

Frames mocking within a broader testing strategy — unit vs integration boundaries, the risk of mock-heavy tests masking integration bugs, and team conventions for what to mock.

## What problem mocks solve A **unit test** is meant to verify one small piece of code — typically one class, called the **system/class under test (SUT)** — in isolation. Real classes rarely stand alone: a `OrderService` might depend on a `PaymentGateway`, a `OrderRepository` (database), and an `EmailClient`. These are its **collaborators**. If your test of `OrderService` used the *real* collaborators, it would talk to a real payment provider, a real database, and a real mail server. That makes the test slow, flaky (network/state), hard to set up, and — crucially — it would be testing the collaborators too, so a failure would not point clearly at `OrderService`. A **test double** is any object you substitute for a real collaborator in a test. **Mockito** is the most popular Java library for creating one kind of test double: the **mock**. A *mock* is a dynamically generated object that pretends to be an instance of the type you ask for, records every call made on it, lets you **stub** (program) what its methods return, and lets you **verify** which calls happened. ## How a mock is created ```java import static org.mockito.Mockito.mock; OrderRepository repo = mock(OrderRepository.class); ``` `Mockito.mock(Class<T>)` takes the `Class` object (note the `.class` literal) of the type you want a double for, and returns an instance of that type. It works for **interfaces** (the common case) and for **concrete/abstract classes** (Mockito subclasses them at runtime using a bytecode library, ByteBuddy). The returned object is a real Java object of the right type, so you can pass it anywhere that type is expected — for example into the constructor of the SUT: ```java OrderService service = new OrderService(repo, gateway, email); ``` The declarative equivalent is the **`@Mock` annotation** on a field, which is turned into a real mock by an initializer — either `MockitoAnnotations.openMocks(this)` in a setup method, or the JUnit 5 `@ExtendWith(MockitoExtension.class)` (or JUnit 4 `MockitoJUnitRunner`). `@Mock SomeType x;` is exactly equivalent to `SomeType x = mock(SomeType.class);` — just less boilerplate when you have several. ```java @ExtendWith(MockitoExtension.class) class OrderServiceTest { @Mock OrderRepository repo; @Mock PaymentGateway gateway; } ``` ## Why this achieves isolation Once a collaborator is a mock, it does **nothing real** — it has no database connection, no network call, no business logic. You then *script* only the behaviour your test needs (`when(repo.findById(1L)).thenReturn(Optional.of(order))`). The SUT now runs against fully controlled, deterministic collaborators, so any failure is attributable to the SUT itself. This is the essence of a unit test: narrow the blast radius to one unit. ## Default behaviour of a fresh mock A mock you have *not* stubbed still has to return *something* when a method is called. Mockito returns safe, empty defaults via its default answer (`RETURNS_DEFAULTS` / `ReturnsEmptyValues`): `null` for object references, `0` for numeric primitives, `false` for `boolean`, `'\u0000'` for `char`, and — importantly — **empty collections, not null** for `List`, `Set`, `Map`, `Stream`, `Optional.empty()`, etc. This is deliberate: it means an unstubbed mock will not randomly throw `NullPointerException` when its result is iterated, so you only have to stub the calls that matter to your assertion. ## Mock vs. spy vs. stub vs. fake - **Mock** (`mock(...)`): a fully synthetic double; every method does nothing/returns defaults unless stubbed. - **Spy** (`spy(realObject)`): wraps a *real* instance — calls hit real code unless you override a specific method. - **Stub**: any double whose methods just return canned values (a mock used only for return values is being used as a stub). - **Fake**: a working-but-simplified implementation (e.g. an in-memory repository). Mockito's `mock` is the workhorse; understanding the others tells you when *not* to reach for a mock.

  • Can you mock a final class or a static method with plain Mockito.mock?
    Modern Mockito (with the inline mock maker, default since 5.x) can mock final classes and final methods. Static methods need mockStatic(...) (the inline mock maker / mockito-inline), not plain mock(Class).
  • What's the difference between Mockito.mock(Class) and the @Mock annotation?
    None functionally — @Mock is sugar that produces the same mock, but it must be initialized by MockitoExtension/openMocks. mock(Class) is self-contained and works anywhere.

saying these in an interview costs you the question

  • Saying a mock runs the real method's code by default — it does not (that's a spy)
  • Confusing a mock with a spy
  • Claiming you must stub every method or the test crashes — defaults handle unstubbed calls
  • Thinking mock(...) needs an instance instead of the Class literal

context