What is Kotest's matcher DSL, and how do you assert that a value equals an expected value using shouldBe and shouldNotBe?
answer
- infix: actual shouldBe expected
- shouldNotBe for inequality
- uses == / equals (structural)
- throws AssertionError with diff
- plusOrMinus for doubles
basics
~20 sKotest lets you write checks like normal English. You write 'result shouldBe 5' to say result must equal 5, and 'result shouldNotBe 0' to say it must not equal 0. If the check fails, the test fails with a clear message.
solid answer
~40 sKotest's matcher DSL provides readable assertions via infix functions. `shouldBe` checks equality and `shouldNotBe` checks inequality: `result shouldBe 5`, `result shouldNotBe 0`. They live in `io.kotest.matchers.shouldBe` / `shouldNotBe` and work on any type using structural equality (`equals`). Because they are infix functions, you write `actual shouldBe expected` with no parentheses. On failure Kotest throws an `AssertionError` with a clean diff-style message (expected vs actual). Equality is exact: for floating point you typically use `result shouldBe (3.14 plusOrMinus 0.01)`. These matchers return the receiver, so they can be chained or combined, and they integrate with any Kotest spec style. They are the most-used building block of the assertion library.
code
kotlin · 9 linesimport io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
val sum = listOf(1, 2, 3).sum()
sum shouldBe 6
sum shouldNotBe 0
val pi = 22.0 / 7
pi shouldBe (3.14 plusOrMinus 0.01)go deeper
Can write basic shouldBe/shouldNotBe equality checks and knows they fail the test with a clear message.
Knows shouldBe uses structural equality, that they're infix functions, and reaches for plusOrMinus on doubles.
Explains the matcher abstraction, failure-message diffing, and how the same pattern scales to collection/exception matchers.
Frames readable assertions as a team-wide convention and weighs Kotest assertions vs other libraries for maintainability and onboarding.
## What is the matcher DSL? Kotest is a Kotlin testing framework. Its **assertions library** (`kotest-assertions-core`) provides a fluent, readable **Domain-Specific Language (DSL)** for checking values in a test. A *matcher* is an object that decides whether a value satisfies some condition and, if not, produces a failure message. ## `shouldBe` and `shouldNotBe` These are **infix functions** — Kotlin functions declared with the `infix` keyword that you call as `receiver function argument` (no dot, no parentheses). - `actual shouldBe expected` passes when `actual == expected` (structural equality via `equals`). - `actual shouldNotBe unexpected` passes when `actual != unexpected`. ```kotlin import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe val result = 2 + 3 result shouldBe 5 // passes result shouldNotBe 0 // passes "hello".uppercase() shouldBe "HELLO" val user: User? = findUser() user shouldNotBe null ``` ## What happens on failure When the condition is false Kotest throws an `AssertionError` (specifically an assertion failure) with a message that shows **expected** vs **actual**, often as a structured diff for data classes and collections. This is clearer than a bare `assertEquals`. ## Equality details `shouldBe` uses `==` (the `equals` method). So two `data class` instances with equal fields are equal. For numbers, types must match in the usual Kotlin way. For floating point use the approximate matcher: ```kotlin 0.1 + 0.2 shouldBe (0.3 plusOrMinus 0.0001) ``` ## Why infix? The `infix` modifier makes assertions read like sentences, which is the whole point of the DSL. `shouldBe` is the single most common matcher; everything else (collection, string, exception matchers) builds on the same pattern.
- Why does 'actual shouldBe expected' read better than assertEquals?Argument order is natural (subject first), it's infix so no parentheses, and the failure message is a structured expected-vs-actual diff.
- How do you compare two doubles that may have rounding error?Use the tolerance matcher: actual shouldBe (expected plusOrMinus 0.0001).
Like reading the assertion out loud: 'result should be 5' instead of decoding assertEquals(5, result).
saying these in an interview costs you the question
- Writing the arguments backwards (expected shouldBe actual) and not noticing the message is reversed
- Using shouldBe to compare doubles for exact equality
- Thinking shouldBe uses reference identity instead of equals
- Confusing Kotest's shouldBe with JUnit's assertEquals semantics