Introduction: Why Kotlin Testing is a Superpower, Not a Boring Obligation
\n\nImagine: you wrote an application in Kotlin. It works. You are happy. But a week passes, you add a new feature — and suddenly the old one breaks. Sound familiar? If not — you are either a genius or you have never written code without tests. Kotlin testing is not just a checkbox on a developer's checklist. It is your personal "shield" against bugs, a way to sleep peacefully after deployment, and a tool that makes code cleaner and more understandable.
\n\nIn this article, I will show you where to start testing in Kotlin as a beginner developer. We will cover real examples, popular libraries, and life hacks that will save you hours of debugging. You will learn how to write unit tests, mock dependencies, and test coroutines. Let's go!
\n\nStep 1: Environment Setup — The First 5 Minutes
\n\nBefore writing your first test, you need to add dependencies. If you are using Gradle (and you most likely are), add the following lines to build.gradle.kts:
// build.gradle.kts\ndependencies {\n // JUnit 5 — the foundation of unit testing\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n \n // MockK — the best mocking library for Kotlin\n testImplementation("io.mockk:mockk:1.13.8")\n \n // AssertJ — beautiful and readable assertions\n testImplementation("org.assertj:assertj-core:3.24.2")\n \n // For testing coroutines\n testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")\n}\n\ntasks.test {\n useJUnitPlatform()\n}\n\nDone! Now you have everything you need to write tests. Note: we are using JUnit 5 (not 4) — this is the modern standard that works great with Kotlin. MockK was chosen for a reason: it understands null-safety, extension functions, and other Kotlin features that Mockito handles poorly.
\n\nStep 2: Your First Unit Test in Kotlin
\n\nLet's write a simple class and test it. Suppose we have a discount calculator:
\n\n// DiscountCalculator.kt\nclass DiscountCalculator {\n fun calculateDiscount(price: Double, discountPercent: Int): Double {\n require(price >= 0) { "Price cannot be negative" }\n require(discountPercent in 0..100) { "Discount must be between 0 and 100" }\n return price * (100 - discountPercent) / 100.0\n }\n}\n\nNow let's write a test. Create a file DiscountCalculatorTest.kt in the src/test/kotlin folder:
import org.junit.jupiter.api.Test\nimport org.junit.jupiter.api.assertThrows\nimport org.assertj.core.api.Assertions.assertThat\n\nclass DiscountCalculatorTest {\n \n private val calculator = DiscountCalculator()\n \n @Test\n fun `should correctly calculate a 20% discount`() {\n val result = calculator.calculateDiscount(1000.0, 20)\n assertThat(result).isEqualTo(800.0)\n }\n \n @Test\n fun `should throw an exception for a negative price`() {\n assertThrows<IllegalArgumentException> {\n calculator.calculateDiscount(-100.0, 10)\n }\n }\n \n @Test\n fun `should return the full price for a 0% discount`() {\n val result = calculator.calculateDiscount(500.0, 0)\n assertThat(result).isEqualTo(500.0)\n }\n}\n\nNotice the style: we use backticks for test names in English (Kotlin allows this). This makes tests readable even for non-technical colleagues. AssertJ provides a fluent interface: assertThat(result).isEqualTo(800.0) — reads like an English sentence.
Step 3: Mocks with MockK — When Testing Dependencies
\n\nIn real applications, classes rarely live on their own. They interact with databases, APIs, or other services. To avoid depending on external systems, we use mocks. Suppose we have a service o