skip to content

How do you create a mock with MockK and make one of its methods return a fixed value?

level: juniorimportance: must knowfreq 85%

answer

  1. mockk<T>() = create fake
  2. every { } returns = script return value
  3. strict by default: unstubbed call throws
  4. returnsMany / throws / answers terminators
  5. reified type param

basics

~10 s

Create the fake object with mockk(), then tell it what to return using every { obj.method() } returns value. After that, calling the method gives back the value you set.

solid answer

~40 s

Use the inline function mockk<T>() to create a mock of type T. By default it is a strict mock: every method must be stubbed or the call throws. You define behaviour with every { mock.method(args) } returns result. The lambda after every records which call to stub; returns supplies the canned value. Variants include returnsMany(listOf(...)) for sequential values, throws ex to raise an exception, and answers { ... } for dynamic logic using the call's arguments. Only non-final members are mockable by default; MockK uses bytecode manipulation (and an all-open-style agent) so final Kotlin methods also work via its inline mocking. You typically assign the mock to a val of the interface or class type and inject it into the class under test.

code

kotlin · 6 lines
kotlin
val repo = mockk<UserRepository>()
every { repo.findById(1L) } returns User(1L, "Ada")
every { repo.findById(2L) } returns null

assertEquals("Ada", repo.findById(1L)?.name)
assertNull(repo.findById(2L))

go deeper

for a junior

Can create mockk() and write a basic every { } returns and inject the mock.

for a middle

Knows strict vs relaxed default behaviour and the returnsMany/throws/answers terminators.

for a senior

Explains the reified type param, the recording DSL, and how bytecode/inline mocking handles final members.

for a principal

Reasons about when mocking is the right isolation tool vs fakes/real objects, and the maintenance cost of over-stubbing.

## What a mock is A *mock* is a fake implementation of a type, created at runtime, whose behaviour you script. You use it to isolate the *class under test* from its collaborators (databases, HTTP clients, other services). ## Creating a mock: `mockk<T>()` MockK's entry point is the inline reified function `mockk<T>()`. The `<T>` type parameter is `reified`, so MockK knows the concrete type at runtime and can generate a proxy. ```kotlin interface UserRepository { fun findById(id: Long): User? } val repo: UserRepository = mockk() // type inferred from the val // or val repo = mockk<UserRepository>() // explicit type argument ``` By default `mockk()` produces a **strict** mock: calling any method that has *not* been stubbed throws `MockKException`. (A *relaxed* mock that returns defaults is a separate feature — outside this topic.) ## Stubbing: `every { } returns` You script behaviour with the `every { }` block. Inside the lambda you write the exact call you want to intercept; the value after `returns` is what that call yields. ```kotlin every { repo.findById(1L) } returns User(1L, "Ada") ``` Key stubbing terminators: - `returns x` — return a single value every time. - `returnsMany(listOf(a, b, c))` — return a, then b, then c on successive calls. - `throws SomeException()` — throw instead of returning. - `answers { ... }` — compute the result dynamically; the lambda can read arguments via `firstArg()`, `secondArg()`, or `arg<T>(index)`. ```kotlin every { repo.findById(any()) } answers { User(firstArg(), "dynamic") } ``` ## How it works under the hood MockK uses bytecode manipulation. Because Kotlin classes and methods are `final` by default, MockK ships a JVM agent / inline mocking engine so it can stub even final members without you opening them. This is why `mockk()` works on most Kotlin types out of the box. ## Typical test shape ```kotlin @Test fun returnsUserName() { val repo = mockk<UserRepository>() every { repo.findById(1L) } returns User(1L, "Ada") val service = UserService(repo) assertEquals("Ada", service.nameOf(1L)) } ``` ## Gotchas - A strict mock throws on any unstubbed call — stub everything the test exercises. - The `every` lambda is a *recording* DSL, not a real invocation; don't put assertions there. - One `every` overrides a previous one for the same call signature.

  • What happens if you call a method on a strict mockk() that you never stubbed?
    It throws MockKException complaining there is no answer for that call. You must stub it or use a relaxed mock.
  • How would you make a stubbed method throw instead of return?
    Use every { mock.call() } throws SomeException() instead of returns.

every { } returns is like programming a vending machine: you tell it 'when someone presses B4, dispense this snack'.

saying these in an interview costs you the question

  • Thinking mockk() runs the real method body
  • Putting assertions inside the every { } lambda
  • Believing every call returns null/0 automatically (that's relaxed mocks)
  • Confusing every (stubbing) with verify (checking)
  • Claiming final Kotlin methods can't be mocked by MockK

context