# Testing and Idiomatic Style — Kotlin

Source: https://www.skillbyai.com/en/kotlin/e-testing

> kotlin.test, JUnit 5, MockK, coroutine tests, ktlint and detekt.

## Tests and tooling

`kotlin.test` provides assertions and annotations that map onto JUnit 5 on the JVM and work in multiplatform tests. Function names written in backticks, such as a test called "rejects negative amounts", make test reports readable. **MockK** is a Kotlin-first mocking library supporting final classes, objects and suspend functions (`coEvery`, `coVerify`). **kotlinx-coroutines-test** provides `runTest`, which runs suspend code with virtual time so `delay` does not actually wait. For style, **ktlint** checks and formats code against the Kotlin coding conventions, and **detekt** is a static analysis tool for code smells and complexity; both run in Gradle and CI.

## A coroutine test with MockK

runTest plus coEvery.

```kotlin
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

interface PriceApi { suspend fun price(symbol: String): Double }

class Portfolio(private val api: PriceApi) {
    suspend fun value(holdings: Map<String, Int>): Double =
        holdings.entries.sumOf { (symbol, qty) -> api.price(symbol) * qty }
}

class PortfolioTest {
    @Test
    fun `values holdings using current prices`() = runTest {
        val api = mockk<PriceApi>()
        coEvery { api.price("KT") } returns 10.0
        coEvery { api.price("JV") } returns 2.5

        val total = Portfolio(api).value(mapOf("KT" to 3, "JV" to 4))

        assertEquals(40.0, total)
    }
}
```

## Prefer fakes for simple interfaces

A small hand-written fake implementing an interface is often clearer than a mock. Use MockK when verifying interactions or stubbing hard-to-construct dependencies.

**Quiz:** What does `runTest` from kotlinx-coroutines-test provide?

- [ ] A mocking DSL for suspend functions
- [ ] A linter for coroutine code
- [x] A test coroutine scope with virtual time, so delays are skipped
- [ ] A way to run tests on Android devices only

*Answer:* A test coroutine scope with virtual time, so delays are skipped. Virtual time makes coroutine tests fast and deterministic.
