skip to content

How do you mock a static method with Mockito, and what does Mockito.mockStatic return?

level: middleimportance: should knowfreq 55%

answer

  1. mockStatic returns MockedStatic<T>
  2. when(lambda) not when(value) — no instance
  3. scoped: active until close()
  4. thread-local
  5. needs inline mock-maker

basics

~10 s

Call Mockito.mockStatic(SomeClass.class). It returns a MockedStatic handle you use to stub the static methods. While that handle is open, real static calls are replaced by your stubs; closing it restores the real behavior.

solid answer

~30 s

Use Mockito.mockStatic(SomeClass.class), which returns a MockedStatic<SomeClass> scope object. Inside that scope, call mocked.when(() -> SomeClass.someStatic()).thenReturn(value) to stub the static method, then exercise your code. You verify with mocked.verify(() -> SomeClass.someStatic()). The mock is active only while the MockedStatic is open and only on the current thread, so you must close it when done, normally with try-with-resources. Stubbing replaces the real static implementation for any caller on that thread; once closed, the real method runs again. This requires Mockito's inline mock-maker (the default since Mockito 5; opt-in before that). Frequent need to mock statics usually points at a design issue worth refactoring.

go deeper

for a junior

Knows there is a special API, Mockito.mockStatic, and that you stub with when(() -> ...). May not know the scoping or mock-maker details.

for a middle

Can write a working mockStatic test, stub and verify with lambdas, and knows it returns a MockedStatic handle that must be closed.

for a senior

Explains the scope/lifetime, thread-local behavior, default-answer trap, and the inline mock-maker requirement; reaches for it sparingly.

for a principal

Frames mockStatic as a last resort, steers teams toward injecting Clock/Supplier/seams instead, and weighs the bytecode-instrumentation cost and version policy.

## What is a static method? In Java, an **instance method** belongs to an object — you call `myList.size()`. A **static method** belongs to the class itself, not to any object: `Math.max(1, 2)`, `Instant.now()`, `UUID.randomUUID()`. You call it through the class name, and there is no object to substitute. ## Why mocking statics is hard Normal mocking works by **substitution**: a mock is a fake *object* that implements an interface or subclasses a class, and you pass it into the code under test in place of the real object (dependency injection). Static methods have no object to pass in — the call `UUID.randomUUID()` is hard-wired to the `UUID` class. So ordinary Mockito (`mock(...)`) cannot intercept it; there is nothing to inject. ## What Mockito.mockStatic does `Mockito.mockStatic(SomeClass.class)` installs a temporary interceptor on the **class** itself. It returns a handle of type `MockedStatic<SomeClass>`. While that handle is *open*, every call to a static method of `SomeClass` is routed to Mockito instead of the real implementation. You then: 1. **Stub** — tell it what to return: `mocked.when(() -> SomeClass.foo()).thenReturn("x");` 2. **Exercise** your code, which calls `SomeClass.foo()` and now gets `"x"`. 3. **Verify** (optional): `mocked.verify(() -> SomeClass.foo());` 4. **Close** the handle to remove the interceptor and restore the real method. The `when`/`verify` take a lambda (`Verification`/`MockedStatic.Verification`) rather than a value, because there is no instance to record the call on — the lambda *is* the call expression Mockito watches. ## Scope and lifetime The interceptor is **scoped**: it is active only between creation and `close()`. By default (and unstubbed) the static methods return Mockito's usual defaults (null, 0, empty collection), not the real result, unless you call `.thenCallRealMethod()` or `mockStatic(..., CALLS_REAL_METHODS)`. ## What you get back `MockedStatic<T>` is an `AutoCloseable`. That is the key to using it safely (see the try-with-resources question). It exposes `when(...)`, `verify(...)`, `reset()`, and `close()`. ## The inline mock-maker requirement Intercepting a *class's* static dispatch requires bytecode instrumentation — the **inline mock-maker** (backed by ByteBuddy + the JVM instrumentation API). This is the default in Mockito 5+; in Mockito 3/4 you had to opt in with the `mockito-inline` dependency or a `mockito-extensions/org.mockito.plugins.MockMaker` file. Without it, `mockStatic` throws. ## Design note Needing to mock statics is often a signal that the code reaches out to a hard dependency (clock, random, a static singleton) instead of receiving it via a parameter. Injecting a `Clock`/`Supplier`/interface usually removes the need entirely.

  • Why does mocked.when() take a lambda instead of an expression like normal Mockito?
    There is no instance to record the invocation on, so you pass the static call wrapped in a lambda (a Verification functional interface). Mockito executes it under interception to identify which static method you mean.
  • What happens to a static method you didn't explicitly stub while the MockedStatic is open?
    It returns Mockito's default answer (null/0/empty), not the real result, unless you created the mock with CALLS_REAL_METHODS or call thenCallRealMethod().

saying these in an interview costs you the question

  • Thinking plain Mockito.mock() can stub a static call (no object to inject).
  • Forgetting that unstubbed statics return Mockito defaults, not the real value.
  • Believing the mock is global to the JVM rather than scoped to the handle and thread.

context