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 pageshowhide
explore
- Mocks, Spies and Lifecycle18 questions
- Creating Mocks5 questions
- Relaxed Mocks4 questions
- Spies with spyk5 questions
- Mock Lifecycle and Hygiene4 questions
- Stubbing14 questions
- Returns, Throws and Chaining5 questions
- Answers API5 questions
- Properties and Call Hierarchies4 questions
- Matchers and Capture17 questions
- Argument Matchers5 questions
- Slots and Capturing5 questions
- Vararg Matching3 questions
- Matcher Scoping Rules4 questions
- Verification16 questions
- Call Counts4 questions
- Order and Sequence4 questions
- Exhaustive Verification4 questions
- Timeout Verification4 questions
- Mocking Kotlin Constructs13 questions
- Object and Companion Mocking4 questions
- Static and Extension Function Mocking5 questions
- Constructor Mocking4 questions
- Coroutines, Annotations and JUnit 514 questions
- Suspend Function Mocking4 questions
- Annotation-Driven Setup5 questions
- JUnit 5 Integration5 questions
questions
92 · 6 sectionsMockK 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.
basics
~20 sMockK 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.
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?
basics
~20 sanswers 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.
A mock created with MockK's `mockk<T>(relaxed = true)` answers calls you never stubbed. What value does it actually return, per return type?
basics
~20 sMockK 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.
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?
basics
~20 sspyk(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.
In MockK, what is the difference between clearAllMocks() and unmockkAll(), and which one do you need after a test has called mockkObject or mockkStatic?
basics
~20 sclearAllMocks 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.
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?
basics
~20 sThe 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.
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?
basics
~20 sMockK 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 }.
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?
basics
~20 sChain 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.
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?
basics
~20 sThe 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.
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?
basics
~20 sandThen 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.
Beyond `any()` and `eq()`, what argument matchers does MockK offer, and how do you choose between them when stubbing or verifying a call?
basics
~10 sMockK 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.
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.
basics
~20 sMatchers 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.
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?
basics
~20 sA 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.
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?
basics
~20 sIn 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.
How does MockK's `eq()` decide whether an argument matches, and when would you reach for `refEq()` or `cmpEq()` instead?
basics
~10 seq() 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.
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?
basics
~20 sIt 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) { ... }.
What does MockK's `verify { repo wasNot Called }` assert, and how is that different from `verify(exactly = 0) { repo.save(any()) }`?
basics
~20 swasNot 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.
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?
basics
~20 sEvery 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.
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?
basics
~20 sverifyAll 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.
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?
basics
~20 sverifyOrder 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.
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?
basics
~20 sanyConstructed<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.
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?
basics
~20 sNo 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.
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?
basics
~20 sPass 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.
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?
basics
~20 sEverything 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.
What exactly does MockK's unmockkConstructor(Foo::class) restore, and how does it differ from letting a broad unmockkAll run instead?
basics
~20 sunmockkConstructor 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.
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?
basics
~20 sIt 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.
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?
basics
~20 sIt 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.
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?
basics
~20 sProperty 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.
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?
basics
~20 sIt 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.
Compare MockK's @MockK, @RelaxedMockK and @SpyK: what object does each property end up holding, and how must each property be declared?
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.