Mock — o que é, objetos mock e bibliotecas para testes

Autor: IT Sectr Publicado: 2026-04-10 Tempo de leitura: 8 min

Mock é um objeto substituto que imita o comportamento de um componente real e permite verificar interações com ele. Ao contrário de Stub, que simplesmente retorna um valor pré-definido, Mock registra o fato da invocação do método, os argumentos passados e o número de chamadas. De acordo com Mockito (2024), Mock é o tipo mais popular de Test Double em projetos Java e Kotlin, usado em mais de 70% dos testes unitários de aplicativos móveis.

Pontos principais

  • Mock — um objeto que verifica interação: quais métodos foram chamados, com quais argumentos e quantas vezes
  • Mockito — a biblioteca mais popular para criar Mocks em projetos Java e Android
  • MockK — uma alternativa ao Mockito para Kotlin com suporte nativo a corrotinas e classes seladas
  • Behavior verification — a diferença chave entre Mock e Stub: Mock verifica comportamento, não estado
  • Over-mocking — o principal antipadrão: mocks devem ser usados apenas para dependências externas

O que é Mock?

Mock é um objeto criado por um framework de mocking (Mockito, MockK, EasyMock) que simula uma interface ou classe e registra todas as chamadas aos seus métodos. O desenvolvedor define expectativas: o método X será chamado com os argumentos Y e retornará Z. Após a execução do teste, o Mock verifica se as expectativas corresponderam às chamadas reais.

O termo vem da metáfora teatral de Test Doubles: um Mock é um “impostor” que não apenas fica no palco (como um Dummy) mas desempenha um papel e verifica se a interação com ele foi correta. Se o código sob teste não chamou o método que o Mock esperava, ou o chamou com argumentos incorretos — o teste falha com uma mensagem de expectativa violada.

Como o Mock funciona

Um Mock é criado através da fábrica do framework: mockk<MyInterface>() ou Mockito.mock(MyClass.java). O framework gera um objeto proxy que intercepta todas as chamadas de métodos. Cada chamada é comparada com expectativas pré-definidas. Se a chamada corresponder a uma expectativa — o valor especificado é retornado. Se não — o Mock retorna um valor padrão ou lança uma exceção, dependendo da configuração.

Quando o Mock é necessário

Mock é essencial quando o código sob teste interage com componentes que têm efeitos colaterais: enviar dados para um servidor, escrever em um banco de dados, logging, analytics, navegação, exibir diálogos do sistema. Sem Mocks, essas interações não podem ser verificadas sem executar infraestrutura real. De acordo com o Google Testing Blog, Mock é a única maneira de verificar se um aplicativo realmente enviou um evento de analytics sem iniciar um servidor de teste.

Mock vs. Stub: comparação detalhada

A diferença entre Mock e Stub é um dos tópicos mais debatidos em testes. Ambos os tipos substituem uma dependência real, mas de formas fundamentalmente diferentes.

CritérioMockStub
Pergunta principalO método foi chamado?Qual resultado foi retornado?
VerificaçãoComportamento (verify)Estado (assert)
Retorno de dadosOpcionalObrigatório
Exemploverify(analytics).logEvent(“click”)assertEquals(5, repository.getCount())
Quando usarEfeitos colateraisRetorno de dados

Regra prática: Mock ou não

Um teste simples para decidir: pergunte a si mesmo “se eu excluir esta linha de código, o teste falhará?” Se o teste verifica um valor de retorno — você precisa de um Stub (verificação baseada em assert). Se o teste verifica se o código chamou um método com os argumentos corretos — você precisa de um Mock (verificação baseada em verify). Esta dicotomia segue o padrão Command-Query Separation: métodos que mudam estado (commands) precisam de Mocks; métodos que retornam dados (queries) precisam de Stubs.

Mockito vs. MockK: comparação de bibliotecas

Escolher entre Mockito e MockK é uma das primeiras decisões ao configurar o stack de testes para um projeto Android em Kotlin. Ambas as bibliotecas cumprem o mesmo propósito, mas com abordagens diferentes para recursos específicos do Kotlin.

Mockito: clássico comprovado

Mockito é o padrão de facto para projetos Java. A versão 5.x suporta mocking para classes finais, métodos estáticos e construtores graças ao MockMaker embutido. Para projetos Kotlin, o Mockito requer configuração adicional: extensões mockito-kotlin para sintaxe melhorada, mockito-inline para classes finais. O Mockito não suporta corrotinas Kotlin e funções suspend sem adaptadores adicionais.

MockK: abordagem Kotlin-first

MockK foi criado especificamente para Kotlin. Ele suporta nativamente corrotinas (coEvery, coVerify), classes seladas, classes de dados, singletons de objeto e funções de extensão. A sintaxe do MockK usa DSL com blocos lambda, o que parece natural em código Kotlin. O MockK também suporta mocking de propriedades sem configuração adicional — isso é importante para projetos Android que usam LiveData, StateFlow e Delegates.

kotlin
// Mockito + mockito-kotlin
val repository = mock<UserRepository>()
whenever(repository.getUser(1)).thenReturn(user)

// MockK
val repository = mockk<UserRepository>()
every { repository.getUser(1) } returns user

Comparação de desempenho

Benchmarks (JVM Benchmark, 2024) mostram que MockK cria objetos mock 15–20% mais rápido que o Mockito para projetos Kotlin graças ao trabalho direto com bytecode Kotlin em vez de Java Reflections. Para projetos com milhares de testes unitários, a diferença na velocidade de build pode ser notável: o MockK economiza 30–60 segundos em uma execução completa de testes em projetos grandes.

Exemplos de testes Mock em Kotlin

Vamos examinar três cenários: testar um ViewModel com dependências Mock, testar um UseCase verificando chamadas de API e testar corrotinas com coVerify.

Exemplo 1: ViewModel com Mock de analytics

kotlin
class ProfileViewModelTest {
    private val analytics = mockk<AnalyticsService>()
    private val repo = mockk<UserRepository>()
    private val vm = ProfileViewModel(repo, analytics)

    fun `profile opened logs analytics event`() {
        every { analytics.logEvent("profile_opened") } returns Unit

        vm.onViewCreated()

        verify { analytics.logEvent("profile_opened") }
    }
}

Exemplo 2: UseCase com verificação assíncrona

kotlin
class SendMessageUseCaseTest {
    private val api = mockk<MessagingApi>()
    private val useCase = SendMessageUseCase(api)

    fun `send message with correct payload`() = runTest {
        val message = Message(text = "Hello", userId = 42)

        coEvery { api.sendMessage(any()) } returns MessageResult.Sent("msg_1")

        val result = useCase.execute(message)

        coVerify {
            api.sendMessage(match {
                it.text == "Hello" && it.userId == 42
            })
        }
        assertTrue(result is MessageResult.Sent)
    }
}

Exemplo 3: verificação de argumentos com ArgumentCaptor

kotlin
class OrderUseCaseTest {
    private val api = mockk<OrderApi>()
    private val useCase = OrderUseCase(api)
    private val slot = slot<OrderRequest>()

    fun `order request contains correct items`() = runTest {
        coEvery { api.placeOrder(capture(slot)) } returns OrderResult.Placed("order_1")

        useCase.execute(listOf("item_a", "item_b"))

        assertEquals(2, slot.captured.items.size)
        assertEquals("item_a", slot.captured.items[0])
    }
}

Melhores práticas de testes Mock

O uso eficaz de Mock no desenvolvimento móvel requer disciplina. Violar essas regras transforma os testes em obstáculos frágeis que quebram a cada refatoração.

Mock apenas nos limites externos da aplicação

Uma regra rígida: Mocks devem ser criados apenas para dependências que cruzam o limite da aplicação: clientes de API, bancos de dados, sistema de arquivos, serviços do sistema (LocationManager, BluetoothAdapter, Camera). Classes internas da aplicação — entidades de domínio, Value Objects, utilitários simples — não devem ser substituídas por Mocks. Seu comportamento é testado através de objetos reais.

Um assert / verify por teste

Cada teste deve conter exatamente uma verificação lógica — ou verify (para Mock) ou assert (para Stub). Não misture verificação de estado e comportamento em um único teste. Se você precisa verificar tanto uma chamada de API quanto seu resultado — crie dois testes separados com nomes diferentes. Esta regra, conhecida como “um assert por teste”, remonta às recomendações de Kent Beck (2002).

  • Use relaxUnitFun = true no MockK para métodos que retornam Unit — caso contrário, Mock lançará uma exceção em uma chamada não especificada
  • Limite verify apenas a chamadas críticas — não verifique cada getter e setter, isso torna os testes frágeis
  • Aplique ArgumentMatchers com critério — any() oculta detalhes importantes se o argumento for crítico para a lógica de negócio
  • Não abuse de verifyNoMoreInteractions — este método torna os testes desnecessariamente rígidos a qualquer mudança no código de produção
  • Use @MockkAnnotations para inicialização automática de objetos Mock — isso reduz boilerplate e melhora a legibilidade

Técnicas avançadas de testes Mock

Além do mocking básico, existem técnicas avançadas que resolvem tarefas específicas no desenvolvimento móvel: testar multithreading, verificar estado de Flow e mocking parcial de objetos reais.

Mock parcial com spyK

Spy (ou mock parcial) permite criar um objeto que delega chamadas à implementação real mas permite sobrescrever métodos individuais. No MockK, spyk é criado com base em uma instância de classe real: val repo = spyk(InMemoryUserRepository()). Chamadas com expectativas definidas via every passam pelo Mock; o restante passa pelo objeto real. Spy é especialmente útil para testar código legado onde a injeção de dependência ainda não foi implementada e você só precisa sobrescrever um método.

Testando StateFlow com Turbine

Em projetos Android modernos usando Jetpack Compose, o ViewModel expõe estado através de StateFlow. O MockK permite mockar dependências Flow, e a biblioteca Turbine simplifica a verificação de emissões. O padrão clássico: MockK para um UseCase que retorna um Flow, Turbine para verificar as emissões do ViewModel. Este stack é recomendado pela documentação de Android Testing (Google, 2024) para projetos com Kotlin Coroutines.

kotlin
class SearchViewModelTest {
    private val searchUseCase = mockk<SearchUseCase>()
    private val vm = SearchViewModel(searchUseCase)

    fun `search emits results`() = runTest {
        coEvery { searchUseCase.search("android") } returns
            flowOf(SearchResult.Success(listOf(Item("Android TDD"))))

        vm.search("android")

        vm.state.test {
            val state = awaitItem()
            assertTrue(state.items.isNotEmpty())
            cancelAndIgnoreRemainingEvents()
        }
    }
}

Perguntas frequentes

Como o Mock difere do Mockito?

Mock é um conceito, um tipo de Test Double que verifica comportamento. Mockito é uma biblioteca para criar objetos Mock em Java e Android. Outras bibliotecas: MockK (Kotlin), EasyMock (Java), Cuckoo (iOS).

Como o Mock funciona com corrotinas Kotlin?

Para testar funções suspend com Mock, use MockK (coEvery / coVerify) ou Mockito com mockito-kotlin. O MockK suporta corrotinas nativamente: coEvery define o comportamento de uma função suspend, coVerify verifica sua chamada dentro de uma corrotina. Todas as chamadas suspend devem ser executadas dentro de runTest (kotlinx-coroutines-test).

Um Mock pode retornar valores diferentes em chamadas repetidas?

Sim. No MockK, use returnsMany: every { api.getData() } returnsMany listOf(response1, response2). No Mockito — uma cadeia de thenReturn(value1).thenReturn(value2). Isso é útil para testar comportamento com chamadas sequenciais retornando respostas diferentes.

Como limpar o estado do Mock entre testes?

No MockK, use a anotação @MockK com relaxed = true e chame clearMocks(mock) no método @After. No MockitoMockito.reset(mock). Melhor prática: criar um novo Mock para cada teste via @Before para eliminar interferência entre testes.

Como o Mock lida com classes seladas em Kotlin?

MockK funciona corretamente com classes seladas: every { useCase() } returns Result.Success(data). Mockito não suporta classes seladas diretamente, exigindo soluções alternativas. Esta é uma razão pela qual o MockK é recomendado para projetos Kotlin em vez do Mockito.

Resumo

  • Mock — um tipo de Test Double que verifica comportamento (verify), não estado (assert) das dependências
  • Mockito — o padrão para Java/Android, MockK — a escolha Kotlin-first com suporte para corrotinas e classes seladas
  • Regra principal: Mock para limites externos (rede, BD, serviços do sistema), objetos reais para classes internas
  • Over-mocking — o principal antipadrão: substituição excessiva de dependências torna os testes frágeis e inúteis
  • Um teste — uma verificação lógica: verify para Mock ou assert para Stub, mas não ambos no mesmo teste
  • ArgumentCaptor / slot — a maneira correta de verificar argumentos de chamadas Mock em vez de any() cego
  • MockK é recomendado para projetos Kotlin: coEvery e coVerify funcionam nativamente com corrotinas sem adaptadores adicionais

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também