skip to content

MockK

MockK is the de facto mocking library for Kotlin on the JVM, built around an every/verify DSL and able to mock the things Java mockers struggle with: final classes, objects, top-level and suspend functions. Interviewers use it to probe whether you understand test doubles mechanically, not just by recipe.

on this pageshow

explore

questions

92 · 6 sections

MockK can create a mock of a final Kotlin class without you marking it `open` or extracting an interface. Explain the instrumentation mechanism that makes that possible, and what it means for how the mock instance itself is produced.

level: middleimportance: must knowfreq 55%
basics
~20 s

MockK ships a JVM agent that rewrites class bytecode in place, inserting a dispatch hook into method bodies — so final classes and final methods are interceptable. The instance itself is allocated without running any constructor, then every call is routed to MockK's stub registry.

open as a page

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%
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.

open as a page

A mock created with MockK's `mockk<T>(relaxed = true)` answers calls you never stubbed. What value does it actually return, per return type?

level: middleimportance: must knowfreq 45%
basics
~20 s

MockK generates a per-type default: Unit for Unit, 0 for numeric types, false for Boolean, an empty String, empty arrays — and for any other type, including your own domain classes, a brand-new mock of that type which is itself relaxed.

open as a page

In MockK, when you write spyk(existingInstance), what relationship does the resulting spy have with the instance you passed in — and what breaks if you assume it is a wrapper that delegates to that object?

level: middleimportance: must knowfreq 45%
basics
~20 s

spyk(obj) does not delegate. MockK builds a fresh instrumented instance of the same class and copies obj's fields into it, shallowly. Spy and original are then separate objects; state changes on one are invisible to the other.

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

Inside MockK's `answers { }` block, how do you read the arguments the caller actually passed, and what are `firstArg()`, `arg<T>(n)` and `lastArg()` really doing?

level: middleimportance: must knowfreq 50%
basics
~20 s

The block runs at call time with an answer scope exposing the invocation. Use firstArg<T>(), secondArg<T>(), thirdArg<T>(), lastArg<T>() or arg<T>(n) for a zero-based index. Each is an indexed read of the argument list plus an unchecked cast to T, so a wrong T fails at that line.

open as a page

In MockK, how do you stub and verify a Kotlin property on a mock — both a read-only `val` and an assignable `var` — and what is MockK actually intercepting when you do?

level: middleimportance: must knowfreq 55%
basics
~20 s

MockK intercepts accessor calls, not fields. Stub reads with every { mock.prop } returns x. An assignment is a setter call needing an answer, so use justRun { mock.prop = any() }, and assert with verify { mock.prop = 5 }.

open as a page

In MockK, how do you make one stubbed function return a different value on each successive call, and what does that stub return once the list of values is used up?

level: middleimportance: must knowfreq 55%
basics
~20 s

Chain answers: every { c.next() } returns 1 andThen 2 andThen 3, or returnsMany listOf(1, 2, 3). MockK hands out one entry per matching call, in order. When the list runs out it repeats the last entry forever — it does not throw and does not restart.

open as a page

In a MockK test you write `every { repo.find(any()) } returns A` and later, in the same test, `every { repo.find(1) } returns B`. Which stub wins, and does re-stubbing reset an existing answer chain or the mock's recorded calls?

level: seniorimportance: must knowfreq 40%
basics
~20 s

The most recently registered matching stub wins, so find(1) returns B and everything else returns A. Declaration order decides, not how specific the matcher is. Re-stubbing a call installs a new answer, so any chain in the old one is abandoned and sequencing starts over — but recorded calls are untouched.

open as a page

In MockK, how does `andThenAnswer` differ from `andThen`, and when do you need a computed answer for the second and later calls of the same stub?

level: middleimportance: should knowfreq 28%
basics
~20 s

andThen appends a constant value to the sequence; andThenAnswer appends a lambda that runs at call time with the answer scope, so it can read the arguments, compute a result or call the original. Use it whenever a later step must depend on that call's input, not on a value known up front.

open as a page

Beyond `any()` and `eq()`, what argument matchers does MockK offer, and how do you choose between them when stubbing or verifying a call?

level: middleimportance: must knowfreq 60%
basics
~10 s

MockK adds neq, isNull() and isNull(inverse = true), ofType<T>(), less/more (with andEquals) and range for Comparables, match { } predicates, the and/or/not combinators, and refEq/nrefEq/cmpEq for reference or compareTo equality.

open as a page

In MockK, why can matcher functions such as any() or match { } only be written inside an every, coEvery or verify block? Explain what actually happens at compile time and at runtime when one of them is called.

level: middleimportance: must knowfreq 45%
basics
~20 s

Matchers are declared on MockK's MockKMatcherScope, the receiver of every/verify blocks, so elsewhere they do not compile. Inside, a call like any() registers a matcher with MockK's call recorder and returns a generated dummy value the recorder binds back to that argument position.

open as a page

A MockK test captures a collaborator's argument with a CapturingSlot, but the mocked method is invoked several times during the test. Which value does the slot hold when the test asserts, and how would you keep every call's argument instead?

level: middleimportance: must knowfreq 45%
basics
~20 s

A CapturingSlot holds one value: each matching call overwrites it, so you end up with the last call's argument. To keep them all, capture into a MutableList — capture(list) appends every matching call's argument in call order.

open as a page

You are stubbing a MockK mock of an interface method declared as fun log(vararg parts: String). Why does every { log.log(any()) } fail to match a call that passes three arguments, and what does MockK give you to match a call with any number of vararg elements?

level: middleimportance: must knowfreq 35%
basics
~20 s

In the every block each value you write in a vararg position records one element matcher, so any() describes a call with exactly one element. Use MockK's anyVararg() spread into the call — every { log.log(*anyVararg()) } — to match any number of elements.

open as a page

How does MockK's `eq()` decide whether an argument matches, and when would you reach for `refEq()` or `cmpEq()` instead?

level: middleimportance: should knowfreq 45%
basics
~10 s

eq() compares structurally: arrays are compared by content, everything else by equals(). refEq() compares by reference identity, and cmpEq() compares with compareTo, which matters for types like BigDecimal where equals and compareTo disagree.

open as a page

In MockK, what does a bare `verify { mailer.send(any()) }` with no count parameter actually assert, and how do you assert that the call happened exactly once?

level: middleimportance: must knowfreq 50%
basics
~20 s

It asserts at least one matching call. MockK's verify defaults are atLeast = 1, atMost = Int.MAX_VALUE and exactly = -1 (unspecified), so two or ten matching calls also pass. For exactly-once, write verify(exactly = 1) { ... }.

open as a page

What does MockK's `verify { repo wasNot Called }` assert, and how is that different from `verify(exactly = 0) { repo.save(any()) }`?

level: juniorimportance: should knowfreq 40%
basics
~20 s

wasNot Called asserts the mock received zero recorded calls at all — any method, any arguments. exactly = 0 is narrower: that one method with those matchers never matched, while other calls on the same mock are allowed.

open as a page

MockK's confirmVerified(mock) throws when a mock has recorded calls that nothing verified. Mechanically, which invocations end up in that record, what marks one as verified, and where in a test must the call be placed?

level: middleimportance: should knowfreq 45%
basics
~20 s

Every real invocation on the mock is recorded — stubbed, relaxed-default, property access, suspend calls alike. Any verify block whose matchers match a recorded call marks it verified. confirmVerified verifies nothing itself; it asserts the leftover set is empty, so it goes last.

open as a page

MockK offers verifyAll alongside verifyOrder and verifySequence. What does verifyAll assert that a plain verify does not, which calls fall inside its scope, and how does its failure condition differ from verifySequence's?

level: middleimportance: should knowfreq 35%
basics
~20 s

verifyAll is exhaustive but order-free: every call you list must have happened, and every recorded call on the mocks named in the block must be matched by some entry. verifySequence adds the requirement that the order match exactly.

open as a page

In MockK, what exactly does a verifyOrder block check about the calls a mock recorded — which calls are allowed to appear between the ones you list, how do you assert that the same call happened twice in a row, and what makes the block fail?

level: middleimportance: should knowfreq 45%
basics
~20 s

verifyOrder asks whether the listed calls appear in that relative order somewhere in MockK's chronological call record. Any other calls in between are ignored. A repeat must be listed once per occurrence. It fails only when no in-order match exists.

open as a page

After calling MockK's mockkConstructor(Foo::class), what does anyConstructed<Foo>() actually stand for, and which Foo instances does a stub recorded on it affect?

level: middleimportance: must knowfreq 40%
basics
~20 s

anyConstructed<Foo>() is not an instance — it is a single shared handler for the class. Every Foo constructed while the class is mocked routes its calls through it, so one stub applies to all of them. Methods you never stub fall through to the real implementation.

open as a page

When you call MockK's mockkObject(PricingRules) on a Kotlin object declaration, is a new instance created to stand in for the singleton, and what happens when the test then calls a method you never stubbed?

level: middleimportance: must knowfreq 40%
basics
~20 s

No new instance: MockK patches the existing singleton in place, so its identity and state are unchanged and every holder of a reference sees the patch. Unstubbed methods still run the real implementation — an object mock is a spy, not a strict mock.

open as a page

When you use MockK's mockkStatic to stub a Kotlin top-level or extension function, how do you work out the exact string to pass, and what can change that name?

level: middleimportance: must knowfreq 45%
basics
~20 s

Pass the JVM name of the file facade class: package plus source file name with Kt appended. Greetings.kt in com.acme becomes com.acme.GreetingsKt. A @file:JvmName annotation on that file replaces the name, and the string must match exactly.

open as a page

MockK's mockkObject patches a singleton in place rather than substituting it. Concretely, who can observe that patch while it is active, and what does unmockkObject give back — and what does it not give back?

level: seniorimportance: must knowfreq 34%
basics
~20 s

Everything in that JVM sees it: all threads, all concurrently running tests, all reference holders, and any production path reaching the singleton. There is no per-test or per-thread scoping. unmockkObject restores real behaviour only — not the object's mutated state, nor side effects real code already performed.

open as a page

What exactly does MockK's unmockkConstructor(Foo::class) restore, and how does it differ from letting a broad unmockkAll run instead?

level: middleimportance: should knowfreq 26%
basics
~20 s

unmockkConstructor removes the constructor instrumentation for exactly the classes you name and drops the stubs recorded against them, so later constructions produce ordinary objects. unmockkAll removes every static, object and constructor registration in the JVM, including ones other code installed.

open as a page

In a test class that declares MockK's @MockK and @SpyK properties, what does MockKAnnotations.init(this) actually do, and what breaks if you forget to call it?

level: middleimportance: must knowfreq 55%
basics
~20 s

It reflects over the given instance, creates a mock or spy for every MockK-annotated property and assigns it. Without it those lateinit properties are never set, so the first use throws UninitializedPropertyAccessException — the annotations do nothing on their own.

open as a page

In a JUnit 5 test class annotated with @ExtendWith(MockKExtension::class), what work does MockK's extension actually perform, and at which points of the test lifecycle does it perform it?

level: middleimportance: must knowfreq 45%
basics
~20 s

It initialises annotated mock properties on each new test instance, resolves MockK-annotated test parameters, and afterwards runs unmockkAll() plus clearAllMocks() — after every test method, or after the whole class when the instance lifecycle is PER_CLASS.

open as a page

A MockK test declares `@MockK lateinit var repo: Repo` and builds the subject in a property initialiser: `val service = OrderService(repo)`. Why does it blow up, and how do you order the setup correctly?

level: seniorimportance: must knowfreq 38%
basics
~20 s

Property initialisers run when the test instance is constructed, before any setup method and before MockKAnnotations.init(this) assigns the mocks. So repo is still unset and the initialiser throws UninitializedPropertyAccessException. Build the subject after init, or let @InjectMockKs do it.

open as a page

How does MockK's @InjectMockKs decide what to put into the subject under test — does it use the constructor or the properties, and does it match by name or by type?

level: seniorimportance: must knowfreq 42%
basics
~20 s

It draws from the doubles created in the same test class. If the annotated property has no instance yet, MockK constructs the subject through a constructor it can satisfy; if you assigned an instance, it injects into its properties. Matching considers type and name, tunable with lookupType.

open as a page

Compare MockK's @MockK, @RelaxedMockK and @SpyK: what object does each property end up holding, and how must each property be declared?

level: middleimportance: should knowfreq 40%
basics
~20 s

@MockK and @RelaxedMockK both put a mock in the property and go on lateinit var of the mocked type; @RelaxedMockK equals @MockK(relaxed = true). @SpyK wraps a real value you supply, so its property must be an initialised var, not lateinit.

open as a page