Testes em Kotlin: unit, integration, e2e nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que testes avançados são a base de um código Kotlin confiável

No desenvolvimento moderno com Kotlin, escrever código é apenas metade do trabalho. A verdadeira maestria se revela na capacidade de criar sistemas confiáveis, testáveis e fáceis de manter. Testes unitários básicos são familiares a todos, mas quando o projeto cresce para uma arquitetura de microsserviços ou lógica de negócios complexa, verificações simples não são mais suficientes. Testes avançados incluem não apenas o isolamento de classes, mas também a verificação da interação entre componentes (testes de integração) e a reprodução completa de cenários de usuário (E2E).

Este artigo é destinado a desenvolvedores que já conhecem os fundamentos do Kotlin e desejam elevar a qualidade de seus projetos a um novo patamar. Abordaremos três níveis-chave de teste: unit, integration e e2e, utilizando ferramentas modernas: MockK, Testcontainers e Ktor Client. Você aprenderá a escrever testes que não apenas "passam", mas que realmente protegem seu código contra regressões.



1. Testes Unitários: Isolamento e Mocks com MockK

Testes unitários são a base da pirâmide de testes. Em um nível avançado, não apenas verificamos funções, mas testamos interações complexas entre objetos, usando mocks. Em Kotlin, a melhor biblioteca para isso é o MockK.



1.1. Recursos Avançados do MockK

Ao contrário do Mockito, o MockK foi escrito especificamente para Kotlin e suporta corrotinas, lambdas e funções de extensão. Vejamos um exemplo de teste de um serviço que usa um repositório e corrotinas:

// Serviço para testarclass UserService(private val repo: UserRepository) {    suspend fun getUserName(id: Long): String {        val user = repo.findById(id)        return user?.name ?: "Unknown"    }}

// Testeclass UserServiceTest { private val repo = mockk<UserRepository>() private val service = UserService(repo)

@Test fun `deve retornar o nome do usuário quando o usuário existe`() = runTest { // given coEvery { repo.findById(1L) } returns User(1, "Alice")

// when val result = service.getUserName(1L)

// then assertEquals("Alice", result) coVerify(exactly = 1) { repo.findById(1L) } }

@Test fun `deve retornar Unknown quando o usuário não for encontrado`() = runTest { // given coEvery { repo.findById(any()) } returns null

// when val result = service.getUserName(99L)

// then assertEquals("Unknown", result) }}

Pontos-chave:

  • coEvery e coVerify — para trabalhar com funções suspend.
  • mockk() cria um mock vazio, spyk() — um mock parcial de um objeto real.
  • Use slots para capturar argumentos.


1.2. Testando Lambdas e Funções de Extensão

O MockK permite mockar funções de extensão, o que é crítico para frameworks como Ktor ou Spring WebFlux:

class StringValidator {    fun String.isValidEmail(): Boolean = this.contains("@")}

// Teste@Testfun `teste de mock de extensão`() { val validator = mockk<StringValidator>() with(validator) { every { "test@mail.com".isValidEmail() } returns true every { "invalid".isValidEmail() } returns false } assertTrue("test@mail.com".isValidEmail()) assertFalse("invalid".isValidEmail())}


2. Testes de Integração: Banco de Dados e Testcontainers

Testes de integração verificam como seu código interage com dependências reais: bancos de dados, filas de mensagens, APIs externas. É aqui que entra o Testcontainers — uma biblioteca que sobe contêineres Docker diretamente durante os testes.



2.1. Configuração do Testcontainers com PostgreSQL

Para uma aplicação Spring Boot, fica assim:

Blogs

Book Recommendations