Testing in Kotlin: A Complete Overview of Frameworks and Tools
Kotlin is a language rapidly gaining popularity in backend development (Spring Boot, Ktor) and Android. However, a powerful language requires adequate testing tools. In this article, we will review the key frameworks and libraries for testing Kotlin applications: from the classic JUnit5 to modern Kotest and MockK. The material will be useful for both beginners and experienced developers transitioning from Java.
1. JUnit5 — The Foundation of Modern Testing
JUnit5 (Jupiter) is the de facto standard for unit testing in Java/Kotlin. In Kotlin, it is used with small but important features.
- Support for lambdas and higher-order functions — tests can be written more concisely.
- Annotations —
@Test,@BeforeEach,@AfterAllwork as in Java. - Assumptions and Assertions — built-in checks.
Example of a simple JUnit5 test with Kotlin:
import org.junit.jupiter.api.Assertions.assertEqualsimport org.junit.jupiter.api.Test
class CalculatorTest {
private val calculator = Calculator()
@Test fun `addition of two numbers should return correct sum`() { val result = calculator.add(2, 3) assertEquals(5, result) }
@Test fun `should throw exception when dividing by zero`() { assertThrows<IllegalArgumentException> { calculator.divide(10, 0) } }}Important: Kotlin allows using spaces in test function names (backticks), making test names readable in natural language.
2. Kotest — A Native Kotlin Framework
Kotest (formerly KotlinTest) is the most comprehensive and flexible framework, entirely written in Kotlin. It offers several styles for writing tests (string spec, specification style, behavior-driven) and powerful built-in matchers.
Key features:
- Property-based testing — automatic generation of test data.
- Data-driven tests — with tables of input data.
- Powerful assertion matchers —
shouldBe,shouldContain,shouldThrow, and others. - Coroutines support — built-in
testCoroutineScope.
Example of a test in the "String Spec" style:
import io.kotest.core.spec.style.StringSpecimport io.kotest.matchers.shouldBeimport io.kotest.matchers.shouldThrow
class UserServiceTest : StringSpec({
val service = UserService()
"should return user by id" { val user = service.getUser(1) user.name shouldBe "Alice" }
"should throw exception for invalid id" { shouldThrow<NoSuchElementException> { service.getUser(-1) } }})Property-based testing in Kotest:
import io.kotest.property.forAllimport io.kotest.property.arbitrary.int
class MathPropertiesTest : StringSpec({ "addition is commutative" { forAll<Int, Int> { a, b -> (a + b) == (b + a) } }})3. MockK — Mocks for Kotlin
Unlike Mockito (which can also be used), MockK is fully adapted to Kotlin's features: it supports sealed classes, object, extension functions, and coroutines.
Main features:
- Concise DSL for creating mocks and stubs.
- Support for relax-mocks (unverified calls).
- Verification of call order and call count.
- Mocks for
suspendfunctions.