Introdução: Por que testar Kotlin é um superpoder, e não uma obrigação chata
\n\nImagine: você escreveu um aplicativo em Kotlin. Ele funciona. Você está feliz. Mas passa uma semana, você adiciona um novo recurso — e de repente algo antigo quebra. Familiar? Se não — ou você é um gênio, ou nunca escreveu código sem testes. Testar Kotlin não é apenas uma marca na lista de verificação do desenvolvedor. É o seu "escudo" pessoal contra bugs, uma maneira de dormir tranquilo após o deploy e uma ferramenta que torna o código mais limpo e compreensível.
\n\nNeste artigo, mostrarei por onde um desenvolvedor iniciante deve começar a testar em Kotlin. Vamos explorar exemplos reais, bibliotecas populares e dicas que economizarão horas de depuração. Você aprenderá a escrever testes unitários, simular dependências e testar corrotinas. Vamos lá!
\n\nPasso 1: Configuração do ambiente — os primeiros 5 minutos
\n\nAntes de escrever o primeiro teste, você precisa adicionar as dependências. Se você usa Gradle (e provavelmente usa), adicione as seguintes linhas ao build.gradle.kts:
// build.gradle.kts\ndependencies {\n // JUnit 5 — base dos testes unitários\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n \n // MockK — a melhor biblioteca para mocks em Kotlin\n testImplementation("io.mockk:mockk:1.13.8")\n \n // AssertJ — asserções bonitas e legíveis\n testImplementation("org.assertj:assertj-core:3.24.2")\n \n // Para testar corrotinas\n testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")\n}\n\ntasks.test {\n useJUnitPlatform()\n}\n\nPronto! Agora você tem tudo o que precisa para escrever testes. Observe: estamos usando JUnit 5 (não o 4) — é o padrão moderno que funciona muito bem com Kotlin. O MockK não foi escolhido por acaso: ele entende null-safety, funções de extensão e outros recursos do Kotlin com os quais o Mockito lida mal.
\n\nPasso 2: Seu primeiro teste unitário em Kotlin
\n\nVamos escrever uma classe simples e testá-la. Suponha que temos uma calculadora de descontos:
\n\n// DiscountCalculator.kt\nclass DiscountCalculator {\n fun calculateDiscount(price: Double, discountPercent: Int): Double {\n require(price >= 0) { "O preço não pode ser negativo" }\n require(discountPercent in 0..100) { "O desconto deve estar entre 0 e 100" }\n return price * (100 - discountPercent) / 100.0\n }\n}\n\nAgora vamos escrever o teste. Crie o arquivo DiscountCalculatorTest.kt na pasta src/test/kotlin:
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 `deve calcular corretamente o desconto de 20%`() {\n val result = calculator.calculateDiscount(1000.0, 20)\n assertThat(result).isEqualTo(800.0)\n }\n \n @Test\n fun `deve lançar exceção para preço negativo`() {\n assertThrows<IllegalArgumentException> {\n calculator.calculateDiscount(-100.0, 10)\n }\n }\n \n @Test\n fun `deve retornar o preço total com desconto de 0%`() {\n val result = calculator.calculateDiscount(500.0, 0)\n assertThat(result).isEqualTo(500.0)\n }\n}\n\nObserve o estilo: usamos crases para os nomes dos testes em português (Kotlin permite isso). Isso torna os testes legíveis até mesmo para um colega não técnico. O AssertJ fornece uma interface fluente: assertThat(result).isEqualTo(800.0) — lê-se como uma frase em inglês.
Passo 3: Mocks com MockK — quando testamos dependências
\n\nEm aplicações reais, as classes raramente vivem sozinhas. Elas acessam bancos de dados, APIs ou outros serviços. Para não depender de sistemas externos, usamos mocks. Suponha que temos um serviço de