skip to content

Mock Lifecycle and Hygiene

Mocks carry stubs and recorded calls between tests unless you reset them, and static/object mocks are global. Interviewers ask about cleanup because flaky cross-test contamination is a real-world debugging staple.

on this pageshow

explore

questions

4

MockK's clearMocks takes flags such as answers, recordedCalls and childMocks. What does each one reset, and why would you ever clear only some of them?

level: middleimportance: must knowfreq 45%

answer

  1. answers = stubs from every
  2. recordedCalls = the verify log
  3. childMocks = auto chained mocks
  4. answers = false → keep stubs, zero counts
  5. clearing ≠ recreating, ≠ unmockk

basics

~20 s

answers drops the stubs from every; recordedCalls empties the interaction log verify reads; childMocks discards auto-created chained mocks. All default to true. Clearing selectively — e.g. answers = false — resets call counts while keeping stubs.

solid answer

~50 s

`clearMocks(mock, answers = ..., recordedCalls = ..., childMocks = ..., verificationMarks = ..., exclusionRules = ...)` resets pieces of a mock's state in place; every flag defaults to `true`. - **answers** — the stubs you configured with `every`/`coEvery`. Clear them and a strict mock throws "no answer found" on the next call. - **recordedCalls** — the log of invocations that `verify` inspects. Clearing resets counts to zero. - **childMocks** — the mocks MockK auto-created for chained calls; clearing discards them so new ones are minted. - **verificationMarks** — which calls `confirmVerified` already considers verified. - **exclusionRules** — rules added by `excludeRecords`. The selective form is the point. `clearMocks(repo, answers = false)` between phases of a long test keeps the stubs and only zeroes the counts. Conversely, clearing everything on a shared fixture is close to recreating it — except the object identity, the mock's name and its relaxed setting all survive, because those were fixed at creation.

code

kotlin · 10 lines
kotlin
val repo = mockk<OrderRepo>()
every { repo.find(any()) } returns Order(1)

service.runPhaseOne()
verify(exactly = 3) { repo.find(any()) }

clearMocks(repo, answers = false)   // stubs survive, counts go to zero

service.runPhaseTwo()
verify(exactly = 1) { repo.find(any()) }

go deeper

for a junior

Know that clearMocks wipes a mock's stubs and its recorded calls, and that it does not create a new mock.

for a middle

Name each flag and what it resets, and give the selective use case (answers = false to keep stubs while zeroing counts).

for a senior

Add the operational angle: clearing is ordering-sensitive, belongs in one place, and is only needed for genuinely shared mocks — and it never un-patches object/static mocks.

for a principal

Position clearing within an isolation policy: prefer fresh mocks, reserve clearing for shared or expensive fixtures, and make the one place it happens obvious to everyone.

## What clearing is, and what it is not A MockK mock carries several independent pieces of state. `clearMocks` resets chosen pieces **in place**: you keep the same object reference, so anything already holding that reference keeps working. It is not re-creation — properties fixed when the mock was built (its type, its `name`, whether it is relaxed, whether it records private calls) are not touched by clearing. ## The pieces of state ```kotlin clearMocks( mock, answers = true, recordedCalls = true, childMocks = true, verificationMarks = true, exclusionRules = true, ) ``` **answers** — the stub table built by `every`/`coEvery`. Each entry maps a call pattern to an answer. Clearing empties the table. On a strict (non-relaxed) mock the next unstubbed call then fails with a MockK exception along the lines of "no answer found for". On a relaxed mock it quietly falls back to relaxed defaults again, because relaxation is a creation property, not a stub. **recordedCalls** — the append-only log of invocations that actually happened. `verify` matches patterns against this log. Clearing it sets every count back to zero; `verify { mock.foo() }` immediately afterwards fails as though the call never happened. **childMocks** — when you stub a chain, MockK invents intermediate mocks to stand in for the intermediate results. Those children hang off the parent. Clearing them means the next chained stubbing creates fresh children; any reference you held to an old child is now detached from the parent's graph. **verificationMarks** — MockK notes which recorded calls have already been matched by a verification, which is what lets an exhaustive check know whether anything is left over. Clearing resets that bookkeeping. **exclusionRules** — rules registered to keep certain calls out of the record. Clearing removes them, so those calls start being recorded again. ## Why selective clearing exists The flags are not decoration; two patterns use them regularly. **Reset counts, keep stubs.** A test drives the system through phase one, verifies, then drives phase two and wants counts starting from zero — without re-declaring a dozen stubs: ```kotlin clearMocks(repository, answers = false) ``` **Reset stubs, keep history.** Rarer, but occasionally you want to re-stub a collaborator differently while still asserting on everything it received so far: ```kotlin clearMocks(repository, recordedCalls = false) ``` ## The trap: clearing after you stubbed Because clearing is a plain function call, it obeys ordering. A blanket clear placed in shared setup that runs *after* per-test stubbing wipes those stubs, and the test then fails with "no answer found" pointing at a method you can plainly see being stubbed two lines up. Decide deliberately whether clearing belongs before setup or after the test, and keep it in exactly one place. ## Clearing versus recreating Creating a fresh mock per test is usually simpler and always safer: no state can survive because the object does not. Reach for `clearMocks` when the mock is genuinely shared — held by an expensive fixture, injected into a long-lived component, or created once for a class — or when you need a mid-test reset. If you find yourself clearing at the start of every test on mocks you also create per test, delete the clear; it is doing nothing. ## Relationship to the bulk functions `clearAllMocks(...)` applies the same reset to every mock MockK knows about, with additional flags selecting *which kinds* to touch — regular mocks, object mocks, static mocks and constructor mocks. It is still a **clear**: it wipes state, it does not undo instrumentation. Removing the instrumentation installed by `mockkObject`/`mockkStatic`/`mockkConstructor` is the job of the `unmockk*` family, which is a different operation entirely. ## Summary sentence to have ready "Clearing resets a mock's stubs, its call log, its child mocks and its verification bookkeeping, selectively via flags; it keeps the same object and its creation-time properties, and it never un-patches anything."

  • After clearMocks(mock) with default flags, what happens on the next call to a method you had stubbed?
    The stub is gone, so behaviour depends on how the mock was created. A strict mock throws a MockK exception reporting that no answer was found for that call. A relaxed mock returns its relaxed default again, because relaxation was fixed at creation time and clearing does not remove it.
  • Does clearMocks turn a relaxed mock into a strict one, or change the mock's identity?
    Neither. Clearing resets state — stubs, recorded calls, child mocks, verification bookkeeping — on the same object. The type, the name given at creation, the relaxed setting and recordPrivateCalls all survive, because they are properties of how the mock was built rather than state it accumulated.

saying these in an interview costs you the question

  • Thinking clearMocks recreates the mock or resets its relaxed setting
  • Assuming clearing removes the instrumentation installed by mockkObject/mockkStatic
  • Believing the flags are all-or-nothing rather than independently settable
  • Placing a blanket clear after per-test stubbing and then blaming MockK for 'no answer found'
  • Calling clearMocks on mocks that are already created fresh per test

context

open as a page

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%

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.

open as a page

A MockK-based test passes on its own but fails when the whole class or suite runs, complaining about a stubbed value or a call count that belongs to a different test. What MockK state makes that possible, and how would you track it down?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Order dependence points at state that outlives a test: JVM-wide registrations from mockkObject/mockkStatic/mockkConstructor, and mocks held in shared or static fields. Bisect by running the suspects in sequence, then add unmockkAll teardown or scoped patches.

open as a page

How would you set the mock-isolation policy for a large Kotlin test suite that uses MockK — fresh mocks per test, clearMocks/clearAllMocks, or unmockkAll teardown — and what are the tradeoffs of each?

level: principalimportance: should knowfreq 24%

basics

~20 s

Default to creating mocks per test so no state can survive. Use clearMocks only for genuinely shared or mid-test resets. Make unmockkAll (or scoped mockk* blocks) mandatory for anything patched globally, in one enforced place.

open as a page