Guia Prático de Testes Unitários com Mockito (Framework de Mock em Java)

Introdução

Este guia aborda os conceitos fundamentais e práticos do uso do Mockito para testes unitários em aplicações Java. O Mockito é uma podeorsa framework que facilita a criação de objetos simulados (mocks) para isolar componentes durante os testes.

Configuração Básica do Mockito

Preparação Inicial

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@InjectMocks
ServicoTeste servicoTeste;
@Mock
ServicoTesteMapper mapeador;

@Mock: Cria um objeto simulado (mock) que começa vazio. Você precisa especificar qual método será chamado, com quais parâmetros, e qual valor retornar.

@InjectMocks: Representa a classe que está sendo testada e que depende dos objetos criados com @Mock. Os mocks serão injetados nesta classe automaticamente.

Anotações para Testes Unitários

import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;

@RunWith(PowerMockRunner.class)
@PrepareForTest({})
@PowerMockIgnore({"javax.net.ssl.*","javax.management.*"})

Inicialização Automática dos Mocks

MockitoAnnotations.initMocks(this);

Atribuição de Valores a Variáveis de Teste

import org.springframework.test.util.ReflectionTestUtils;
ReflectionTestUtils.setField(servicoTeste, "nomeVariavel", "valorParaAtribuir");

Configuração de Retornos de Método

import org.powermock.api.mockito.PowerMockito;
import static org.mockito.ArgumentMatchers.any;

PowerMockito.when(mapeador.teste(any(String.class))).thenReturn("conteudoRetornado");

Simulação de Exceções em Métodos

PowerMockito.when(mapeador.teste(any(String.class))).thenThrow(new ExcecaoPersonalizada());

Configuração de Métodos que Não Retornam Nada

PowerMockito.doNothing().when(servicoTeste).mapeador.teste(any(String.class));

Mock de Objetos Criados com 'new'

Exemplo:

Arquivo arquivo = new Arquivo(caminho);
arquivo.existe();

// Na unidade de teste:
Arquivo arquivoMock = PowerMockito.mock(Arquivo.class);
PowerMockito.whenNew(Arquivo.class).withArguments(arquivo).thenReturn(arquivoMock);
PowerMockito.when(arquivoMock.existe()).thenReturn(true);

Mock de Métodos Estáticos

Na classe de teste:

@PrepareForTest({ClasseEstatica.class})

@Before
public void init(){
    PowerMockito.mockStatic(ClasseEstatica.class);
}

// Chamada do método:
PowerMockito.when(ClasseEstatica.metodoEstatico()).thenReturn("resultado");

Ferramentas Auxiliares para Testes

Anotações Comuns do JUnit

@Test(timeout = 10)
// Teste com tempo limite de 10ms
@Ignore
// Ignora um método ou classe de teste
@RunWith(SpringJUnit4ClassRunner.class)
// Integra JUnit com Spring
@ContextConfiguration(locations = {"classpath:conf/applicationContext.xml"})
// Carrega configurações do Spring
@Resource(name = "servicoBlog")
// Injeção de dependência
@Before
// Executado antes de cada método de teste
@After
// Executado após cada método de teste
@Transactional
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
// Controle de transações

Métodos Úteis do Assert

Assert.assertEquals("mensagem", objetoA, objetoB);
// Verifica se dois objetos são iguais (usa equals())
Assert.assertSame("mensagem", objetoA, objetoB);
// Verifica se dois objetos são a mesma instância (usa ==)
Assert.assertTrue("mensagem", condicaoA);
// Verifica se a condição é verdadeira
Assert.assertFalse("mensagem", condicaoA);
// Verifica se a condição é falsa
Assert.assertNotNull("mensagem", objetoA);
// Verifica se o objeto não é nulo
Assert.assertArrayEquals("mensagem", arrayA, arrayB);
// Verifica se dois arrays são iguais

Exemplo Prático: Teste de Utilitário HTTP

Classe a Ser Testada

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.Map;

public class UtilitarioHttp {
    private String url = "";
    
    /**
     * @param param Parâmetros da requisição
     * @param headers Cabeçalhos customizados
     * @return Resposta do servidor
     */
    public String realizarPost(String param, Map<String,String> headers) {
        HttpPost httpPost = new HttpPost(url);
        RequestConfig configRequisicao = RequestConfig.custom()
                .setSocketTimeout(60000).setConnectTimeout(60000)
                .setConnectionRequestTimeout(60000).build();
        httpPost.setConfig(configRequisicao);
        httpPost.setHeader("Content-Type","application/json;charset=UTF-8");
        
        if (headers != null) {
            headers.forEach((chave,valor) -> httpPost.setHeader(chave,valor));
        }
        
        CloseableHttpClient clienteHttp = HttpClients.custom().disableAutomaticRetries().build();
        httpPost.setEntity(new StringEntity(param,"UTF-8"));
        
        String resultado = null;
        try {
            CloseableHttpResponse resposta = clienteHttp.execute(httpPost);
            HttpEntity entidade = resposta.getEntity();
            resultado = EntityUtils.toString(entidade,"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return resultado;
    }
}

Classe de Teste Unitário

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.IOException;

import static org.mockito.ArgumentMatchers.any;

/**
 * Classe de teste para UtilitarioHttp
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({HttpClientBuilder.class, EntityUtils.class})
@PowerMockIgnore({"javax.net.ssl.*","javax.management.*"})
public class TesteUtilitarioHttp {
    @InjectMocks
    private UtilitarioHttp utilitarioHttp;

    @Mock
    private CloseableHttpClient clienteHttp;
    @Mock
    private CloseableHttpResponse resposta;
    @Mock
    private HttpEntity entidade;
    @Mock
    private HttpClientBuilder construtorCliente;

    @Before
    public void inicializar() {
        PowerMockito.mockStatic(HttpClientBuilder.class);
        PowerMockito.mockStatic(EntityUtils.class);
    }

    /**
     * Teste do método POST do utilitário HTTP
     * Dado: Preparar dados de teste
     * Quando: Enviar requisição válida
     * Então: Verificar resposta esperada
     */
    @Test
    public void testarRequisicaoPost() throws IOException {
        // Dado
        String dados = "{\"id\":\"2\"}";
        
        // Quando
        ReflectionTestUtils.setField(utilitarioHttp, "url", "http://127.0.0.1:8080");
        
        PowerMockito.when(HttpClients.custom()).thenReturn(construtorCliente);
        PowerMockito.when(construtorCliente.disableAutomaticRetries()).thenReturn(construtorCliente);
        PowerMockito.when(construtorCliente.build()).thenReturn(clienteHttp);
        
        PowerMockito.when(clienteHttp.execute(any(HttpPost.class))).thenReturn(resposta);
        PowerMockito.when(resposta.getEntity()).thenReturn(entidade);
        PowerMockito.when(EntityUtils.toString(entidade,"UTF-8")).thenReturn("respostaValida");
        
        String resultado = utilitarioHttp.realizarPost(dados, null);
        
        // Então
        Assert.assertEquals("respostaValida", resultado);
    }
}

Tags: Mockito testes-unitarios java mock JUnit

Publicado em 7-6 08:28