What do confirmVerified and excludeRecords do in MockK, and how do they combine to assert that no unexpected interactions occurred on a mock?
answer
- confirmVerified = verifyNoMoreInteractions
- it fails on any unverified recorded call
- excludeRecords deletes noise from history
- exclude prevents false confirmVerified/sequence failures
- verify marks; confirmVerified checks leftovers
basics
~20 sconfirmVerified(mock) asserts every recorded call on that mock was already verified — failing if any call went unchecked. excludeRecords removes uninteresting calls from the mock's recorded history so they don't trip confirmVerified or sequence checks.
solid answer
~40 sconfirmVerified(mock) is the MockK equivalent of verifyNoMoreInteractions: after your verify blocks, it asserts that no recorded call on that mock remains unverified, catching unexpected interactions. It only counts calls you have NOT yet matched with a verify. excludeRecords { mock.noisy() } proactively deletes matching invocations from the recording, so calls you genuinely don't care about (logging, toString, hashCode-style chatter) don't make confirmVerified or verifySequence fail. There is also verify(verifyBlock) plus confirmVerified pairing, and checkUnnecessaryStub / confirmVerified are related hygiene tools. Typical flow: stub with every, exercise, verify the calls you care about, excludeRecords the noise, then confirmVerified(mock1, mock2) to lock down that nothing else happened.
code
kotlin · 8 linesval repo = mockk<Repo>(relaxed = true)
excludeRecords { repo.heartbeat() }
service.run()
verify(exactly = 1) { repo.save(any()) }
verify(exactly = 1) { repo.flush() }
confirmVerified(repo) // asserts save + flush were the only relevant callsgo deeper
Recognizes confirmVerified asserts nothing extra happened on a mock.
Explains that verify marks calls and confirmVerified checks the unverified remainder.
Combines excludeRecords with confirmVerified to assert no-unexpected-interactions without incidental-call brittleness.
Decides where absence-of-interaction is a real contract worth asserting and standardizes noise-exclusion patterns to keep such tests stable.
## The goal: no unexpected interactions A strong interaction test not only checks the calls you **expect** but also asserts that **nothing else** happened on the mock. MockK provides two cooperating tools. ### `confirmVerified` ```kotlin confirmVerified(repo) confirmVerified(repo, cache) // varargs ``` `confirmVerified(vararg mocks)` asserts that **every recorded call** on each listed mock has **already been verified** by a preceding `verify` / `verifyOrder` / `verifySequence`. If any recorded call was never matched, it throws — this is MockK's `verifyNoMoreInteractions` analogue. It is typically the **last** assertion in a test. ```kotlin service.handle(event) verify(exactly = 1) { repo.save(event) } confirmVerified(repo) // fails if repo got any other call ``` ### `excludeRecords` Some calls are **noise** you never want to assert on — diagnostics, metrics, incidental getters. `excludeRecords` removes matching invocations from the recorded history: ```kotlin excludeRecords { repo.metricsTick() } // drop these from history excludeRecords(current = true) { repo.log(any()) } ``` After exclusion those calls are invisible to `confirmVerified` and to `verifySequence`'s exhaustiveness check, so they won't cause false failures. `excludeRecords` can be applied **before** the exercise (to pre-arm exclusion) or after — the `current` flag controls whether already-recorded calls are also purged. ### How they combine ```kotlin val repo = mockk<Repo>(relaxed = true) excludeRecords { repo.heartbeat() } // ignore heartbeat noise service.run() verify(exactly = 1) { repo.save(any()) } verify(exactly = 1) { repo.flush() } confirmVerified(repo) // save + flush were the ONLY meaningful calls ``` Without `excludeRecords`, the stray `heartbeat()` would leave an unverified call and make `confirmVerified` fail. With it, the heartbeat is erased from history, so `confirmVerified` sees only the verified `save`/`flush`. ## Related hygiene - `verify { }` blocks **mark** calls as verified; `confirmVerified` then checks the leftovers. - MockK also offers `checkUnnecessaryStub(mock)` for the inverse hygiene — flagging `every` stubs that were never called. ## When to use Use `confirmVerified` when the **absence** of extra interactions is part of the contract (e.g., a guard clause must short-circuit and touch nothing). Pair it with `excludeRecords` to keep the assertion focused on meaningful calls and free of incidental-call brittleness.
- How is confirmVerified(mock) different from verify(exactly = 0) { mock.foo() }?exactly = 0 negates one specific call; confirmVerified asserts no unverified call of any kind remains, covering everything you didn't explicitly check.
- Why might you call excludeRecords before exercising the code rather than after?To pre-arm the filter so noisy calls are dropped as they happen; the current flag controls whether already-recorded calls are also purged.
verify ticks off names on a guest list; confirmVerified then checks the room is empty of unlisted guests; excludeRecords waves the catering staff through unticketed.
saying these in an interview costs you the question
- Confusing confirmVerified with confirming stubs were set up
- Thinking confirmVerified re-runs verifications instead of checking leftovers
- Believing excludeRecords stubs behavior (it only filters history)
- Using confirmVerified on a relaxed mock without excluding noise, causing flaky failures