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);
}
}