skip to content

In MockK, what is the difference between clearAllMocks() and unmockkAll(), and which one do you need after a test has called mockkObject or mockkStatic?

level: seniorimportance: must knowfreq 45%

answer

  1. clear = state; unmockk = instrumentation
  2. clearAllMocks leaves objects patched
  3. unmockkAll undoes mockkObject/Static/Constructor
  4. targeted unmockk beats blanket
  5. scoped mockkObject(X) { } auto-unmocks

basics

~20 s

clearAllMocks wipes state — stubs, recorded calls, child mocks — but leaves the instrumentation in place, so an object or static stays patched. unmockkAll removes those registrations and restores original behaviour. After mockkObject/mockkStatic you need unmockkAll.

solid answer

~40 s

They operate on two different things. **clearAllMocks()** is `clearMocks` applied to everything MockK knows about: it resets **state** — `answers`, `recordedCalls`, `childMocks`, plus verification marks and exclusion rules — and takes extra flags (`regularMocks`, `objectMocks`, `staticMocks`, `constructorMocks`) selecting which kinds of doubles to touch. Crucially it does **not** remove instrumentation. After clearing, a `mockkObject`-ed singleton is still patched: MockK is still in its call path and still recording, it just has no stubs left. **unmockkAll()** removes the registrations installed by `mockkObject`, `mockkStatic` and `mockkConstructor`, restoring the real classes and objects. It is the only one of the two that ends the global patch. So after any global patching, teardown must include `unmockkAll()` (or the targeted `unmockkObject`/`unmockkStatic`/`unmockkConstructor`). Regular mocks need neither — being local, they are garbage after the test.

code

kotlin · 11 lines
kotlin
@AfterEach
fun tearDown() {
    unmockkAll()      // removes object/static/constructor patches
    clearAllMocks()   // resets stubs and recorded calls on the doubles
}

// or avoid the teardown entirely for a scoped patch:
mockkObject(FeatureFlags) {
    every { FeatureFlags.enabled("beta") } returns true
    assertTrue(service.betaPath())
} // patch removed here, even on failure

go deeper

for a junior

Remember the pairing: mockkObject/mockkStatic must be undone with unmockk, not with clear.

for a middle

Explain the two categories — per-double state versus global registrations — and which function touches which, including clearAllMocks's kind selectors.

for a senior

Add the operational consequence: a cleared-but-still-patched object leaks JVM-wide, and prefer targeted unmockk* or the scoped block overloads over blanket teardown.

for a principal

Make it structural — global patching needs a single enforced teardown path or, better, scoped blocks so the registration cannot outlive its test.

## Two categories of MockK state To keep these functions straight, separate what MockK holds: 1. **Per-double state** — the stub table, the recorded-call log, child mocks, verification bookkeeping. This lives on the double. 2. **Global registrations** — the fact that an `object`, a class's statics/file facade, or a constructor is currently patched so that MockK sits in its call path. This lives in a JVM-wide registry, keyed by the patched target, and it survives the test method, the test class, and everything else in that JVM until removed. `clearAllMocks` operates on category 1. `unmockkAll` operates on category 2. ## clearAllMocks in detail ```kotlin clearAllMocks( answers = true, recordedCalls = true, childMocks = true, regularMocks = true, objectMocks = true, staticMocks = true, constructorMocks = true, ) ``` The first group of flags mirrors `clearMocks`: which pieces of state to reset. The second group selects which *kinds* of doubles are affected. So you can, for instance, clear only the object mocks' stubs and leave your regular mocks untouched. What it never does is un-patch. Afterwards, a singleton you passed to `mockkObject` remains registered: calls to it still go through MockK, are still recorded, and behave according to whatever default MockK applies for an object mock now that its stubs are gone. From the next test's point of view the object *looks* nearly normal, which is exactly why the leak is hard to spot. ## unmockkAll in detail `unmockkAll()` walks the global registry and undoes every object, static and constructor mock created so far, restoring the original behaviour of those targets. Targeted versions exist — `unmockkObject(SomeObject)`, `unmockkStatic("com.acme.UtilsKt")`, `unmockkConstructor(SomeClass::class)` — and are preferable when you know exactly what you patched, since a blanket call also tears down patches installed by an enclosing fixture. It is about registrations, not about your regular mocks' stubs. A `mockk<Repo>()` held in a field is unaffected by `unmockkAll`; it simply goes out of scope with the test instance. ## Choosing between them | Situation | Use | |---|---| | Shared/expensive mock reused across tests | `clearMocks` / `clearAllMocks` | | Mid-test reset of counts or stubs | `clearMocks` with flags | | Anything patched by `mockkObject` / `mockkStatic` / `mockkConstructor` | `unmockkAll` (or the targeted `unmockk*`) | | Local mocks created per test | neither | They are complementary, not alternatives; a suite that patches globals and also shares fixtures may legitimately do both. ## The scoped alternative MockK 1.13 offers block-scoped overloads — `mockkObject(SomeObject) { ... }`, `mockkStatic("com.acme.UtilsKt") { ... }`, `mockkConstructor(SomeClass::class) { ... }` — that install the patch for the duration of the lambda and remove it on exit, including on exceptions. Where they fit, they remove the whole class of "someone forgot the teardown" bugs, because the registration cannot outlive the block. ## The failure this prevents A test patches a config singleton, stubs a flag to `true`, and tears down with `clearAllMocks()`. The stub is gone but the object stays patched for the rest of the JVM's life. Later tests run against an instrumented singleton whose behaviour is subtly different from production, and any test that patches the same object again inherits a registration it did not install. The symptoms are order-dependent failures that vanish when the failing test is run alone. The fix is one line of teardown, but only if you know which line: `clearAllMocks()` is not it. ## The sentence to say in an interview "`clearAllMocks` resets state; `unmockkAll` removes instrumentation. Clearing a `mockkObject` leaves the object mocked with no stubs — only `unmockk*` gives you the real object back."

  • After clearAllMocks(), what state does a mockkObject-ed singleton still carry?
    Its registration. The object is still patched, so MockK is still intercepting and recording its calls for the rest of the JVM's life; only its stubs, recorded calls and related bookkeeping were reset. Getting the genuine object back requires unmockkObject or unmockkAll.
  • Why might targeted unmockkObject/unmockkStatic be preferable to a blanket unmockkAll?
    unmockkAll tears down every registration in the JVM, including ones installed by an enclosing fixture or a shared base class that expected them to persist for the whole class run. Targeted calls undo exactly what your test installed, keeping the teardown symmetric with the setup and avoiding surprising a neighbour.

Clearing is wiping the whiteboard; unmocking is unplugging the projector that was overlaying the wall. A wiped board still has a projector shining on it.

saying these in an interview costs you the question

  • Using clearAllMocks as teardown for mockkObject/mockkStatic and calling it isolation
  • Believing unmockkAll also wipes stubs from ordinary mockk<T>() instances
  • Thinking regular local mocks need any teardown at all
  • Assuming the patch disappears when the test method ends
  • Treating the two functions as synonyms with different scopes

context