JUnit/Easymock - Como efetuar testes em Beans

3 respostas
G

Estou com a seguinte situação, nescessito criar um teste unitário para um bean (Código 1), porém para que o teste desse certo precisaria utilizar um mock para "simular" uma conexão no banco, creio eu que é a maneira correta e/ou mais facíl. Porém estou com dificuldades de utilizar o Easymock para criar o mock (Código 2) que simularia a conexao ao banco... Até o momento já li alguns tutoriais que encontrei no google, inclusive os da Improve It, mas não achei nada que desse uma dica de como chegar ao resultado esperado.

Código 1
public class NotaFiscalServiceBean extends AbstractCrudServiceBean<NotaFiscal> implements NotaFiscalService { // NOPMD by gkauer on 03/02/10 15:14

	private static final transient Logger LOGGER = Logger.getLogger(NotaFiscalServiceBean.class);

	private static final String MAIL_SEPARATOR = ";";

	private transient DocumentoService documentoService;

	private transient TipoDocumentoService tipoDocumentoService;

	private transient NotaFiscalXmlParserService notaFiscalXmlParserService;

	private transient ConhecimentoTransporteXmlService conhecimentoTransporteXmlService;

	private transient PedidoService pedidoService;

	private transient HistoricoNotaFiscalService historicoNotaFiscalService;

	private transient NotaFiscalXmlService notaFiscalXmlService;

	private transient ItemPedidoService itemPedidoService;

	/**
	 * Consulta nativa, faz join com tabela nao mapeada nos relacionamentos do
	 * Hibernate. Utilizar na tela de pesquisa.
	 * 
	 * @param paginationCriteria
	 *            paginationCriteria
	 * @param findCriteria
	 *            findCriteria
	 * @return PaginatedList
	 */
	public PaginatedList<Map<String, Object>> findNative(final PaginationCriteria paginationCriteria, final FindCriteria findCriteria) { // NOPMD by gkauer on 03/02/10 15:14
		final ValueObjectCriteria<NotaFiscal> voc = (ValueObjectCriteria<NotaFiscal>) findCriteria;

		final Map<String, Object> parameters = new HashMap<String, Object>();
		final StringBuilder query = new StringBuilder();

		query.append(" select distinct ");
		query.append(" nf.codigo_nota_fiscal as id,");
		query.append(" nf.numero_nota_fiscal as numeroNotaFiscal,");
		query.append(" nf.tipo_origem as tipoOrigem,");
		query.append(" nf.valor_total_bruto as valorTotalLiquido,");
		query.append(" nf.data_hora_entrega as dataHoraEntrega,");
		query.append(" nf.data_hora_emissao as dataHoraEmissao,");
		query.append(" cli.razao_social as razaoSocialCliente,");
		query.append(" forn.razao_social as razaoSocialFornecedor,");
		query.append(" a.data_hora_agendamento as dataHoraAgendamento,");
		query.append(" cli.codigo_localizacao as codigoCliente,");
		query.append(" le.codigo_local_entrega as localEntrega");

		query.append(" from nota_fiscal nf ");
		query.append(" inner join pedido_nota_fiscal pnf on pnf.codigo_nota_fiscal = nf.codigo_nota_fiscal");
		query.append(" inner join pedido p on p.codigo_pedido = pnf.codigo_pedido");
		query.append(" inner join nota_fiscal_agendamento nfa on nfa.codigo_nota_fiscal = nf.codigo_nota_fiscal");
		query.append(" join agendamento a on a.codigo_agendamento = nfa.codigo_agendamento");
		query.append(" join local_entrega le on le.codigo_local_entrega = a.codigo_local_entrega");
		query.append(" join localizacao forn on forn.codigo_localizacao = nf.codigo_fornecedor");
		query.append(" join localizacao cli on cli.codigo_localizacao = nf.codigo_comprador");
		query.append(" left join pedido pt on pt.codigo_pedido = a.codigo_pedido_transferencia");

		if (isNotBlank((String) voc.getParameter("numeroPedidoInicial"))) {
			query.append(" and p.numero_pedido >= :numeroPedidoInicial \n");
			parameters.put("numeroPedidoInicial", Integer.decode((String) voc.getParameter("numeroPedidoInicial")));
		}

		if (isNotBlank((String) voc.getParameter("numeroPedidoFinal"))) {
			query.append(" and p.numero_pedido <= :numeroPedidoFinal \n");
			parameters.put("numeroPedidoFinal", Integer.decode((String) voc.getParameter("numeroPedidoFinal")));
		}

		if (isNotBlank((String) voc.getParameter("numeroNotaFiscalInicial"))) {
			query.append(" and nf.numero_nota_fiscal >= :numeroNotaFiscalInicial \n");
			parameters.put("numeroNotaFiscalInicial", Integer.decode((String) voc.getParameter("numeroNotaFiscalInicial")));
		}

		if (isNotBlank((String) voc.getParameter("numeroNotaFiscalFinal"))) {
			query.append(" and nf.numero_nota_fiscal <= :numeroNotaFiscalFinal \n");
			parameters.put("numeroNotaFiscalFinal", Integer.decode((String) voc.getParameter("numeroNotaFiscalFinal")));
		}

		final Double valorInicial = (Double) findCriteria.getParameter("valorInicial");
		if (valorInicial != null) {
			query.append(" and nf.valor_total >= :valorInicial \n");
			parameters.put("valorInicial", valorInicial);
		}

		final Double valorFinal = (Double) findCriteria.getParameter("valorFinal");
		if (valorFinal != null) {
			query.append(" and nf.valor_total <= :valorFinal \n");
			parameters.put("valorFinal", valorFinal);
		}

		final Date dataEmissaoInicial = (Date) findCriteria.getParameter("dataEmissaoInicial");
		final Date dataEmissaoFinal = (Date) findCriteria.getParameter("dataEmissaoFinal");
		if (dataEmissaoInicial != null && dataEmissaoFinal != null) {
			query.append(" and (nf.data_hora_emissao between :dataEmissaoInicial and :dataEmissaoFinal) \n");
			parameters.put("dataEmissaoInicial", dataEmissaoInicial);
			parameters.put("dataEmissaoFinal", dataEmissaoFinal);
		}

		final Date dataEntregaInicial = (Date) findCriteria.getParameter("dataEntregaInicial");
		final Date dataEntregaFinal = (Date) findCriteria.getParameter("dataEntregaFinal");
		if (dataEntregaInicial != null && dataEntregaFinal != null) {
			query.append(" and (nf.data_hora_entrega between :dataEntregaInicial and :dataEntregaFinal) \n");
			parameters.put("dataEntregaInicial", dataEntregaInicial);
			parameters.put("dataEntregaFinal", dataEntregaFinal);
		}

		if (isNotBlank((String) findCriteria.getParameter("tipoOrigem"))) {
			query.append(" and nf.tipo_origem = :tipoOrigem \n");
			parameters.put("tipoOrigem", voc.getParameter("tipoOrigem"));
		}

		if (isNotBlank((String) findCriteria.getParameter("tipoPedido"))) {
			query.append(" and p.tipo_pedido = :tipoPedido \n");
			parameters.put("tipoPedido", voc.getParameter("tipoPedido"));
		}

		if (isNotBlank((String) voc.getParameter("numeroPedidoTransferenciaInicial"))) {
			query.append(" and pt.numero_pedido >= :numeroPedidoTransferenciaInicial \n");
			parameters.put("numeroPedidoTransferenciaInicial", voc.getParameter("numeroPedidoTransferenciaInicial"));
		}

		if (isNotBlank((String) voc.getParameter("numeroPedidoTransferenciaFinal"))) {
			query.append(" and pt.numero_pedido <= :numeroPedidoTransferenciaFinal \n");
			parameters.put("numeroPedidoTransferenciaFinal", voc.getParameter("numeroPedidoTransferenciaFinal"));
		}

		if (findCriteria.getParameter("idFornecedor") != null) {
			query.append(" and nf.codigo_fornecedor = :idFornecedor \n");
			parameters.put("idFornecedor", voc.getParameter("idFornecedor"));
		}

		if (isNotBlank((String) findCriteria.getParameter("idFilial"))) {
			query.append(" and nf.codigo_comprador = :idFilial \n");
			parameters.put("idFilial", Integer.decode((String) voc.getParameter("idFilial")));
		}

		query.append(" order by nf.numero_nota_fiscal desc ");

		final List<Object[]> retorno = findByNativeQuery(query.toString(), parameters);

		final List<Map<String, Object>> resultPesquisa = new ArrayList<Map<String, Object>>();
		for (Object[] obj : retorno) {
			int index = 0;
			final Map<String, Object> map = new HashMap<String, Object>();
			map.put("id", obj[index++]);
			map.put("numeroNotaFiscal", obj[index++]);
			map.put("tipoOrigem", obj[index++]);
			map.put("valorTotalLiquido", Double.valueOf(((BigDecimal) obj[index++]).doubleValue()));
			map.put("dataHoraEntrega", obj[index++]);
			map.put("dataHoraEmissao", obj[index++]);
			map.put("razaoSocialCliente", obj[index++]);
			map.put("razaoSocialFornecedor", obj[index++]);
			map.put("dataHoraAgendamento", obj[index++]);
			map.put("codigoCliente", obj[index++]);
			map.put("localEntrega", obj[index++]);

			resultPesquisa.add(map);
		}

		return new PaginatedList<Map<String, Object>>(resultPesquisa, resultPesquisa.size(), paginationCriteria);
	}

}
Código 2
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

import com.neogrid.bfw.util.FindCriteria;
import com.neogrid.bfw.util.PaginatedList;
import com.neogrid.bfw.util.PaginationCriteria;
import com.neogrid.bfw.util.ValueObjectCriteria;
import com.neogrid.elog.domain.NotaFiscal;
import com.neogrid.elog.service.impl.NotaFiscalServiceBean;

public class TestNotaFiscalServiceBean {

	private transient NotaFiscalServiceBean bean;
	private transient PaginationCriteria paginationCriteria;
	private transient PaginationCriteria paginationCriteriaNulo;
	private transient FindCriteria findCriteriaNulo;
	private transient PaginatedList<Map<String, Object>> listaRetorno;
	private transient final ValueObjectCriteria<NotaFiscal> voc = new ValueObjectCriteria<NotaFiscal>();
	
	
	@Before
	public void setUp() throws Exception {
		
		bean = new NotaFiscalServiceBean();
		
		paginationCriteriaNulo = null;
		findCriteriaNulo = null;
		paginationCriteria = new PaginationCriteria();
		
		Date dataInicial = new Date("01/01/2010");
		Date dataFinal = new Date("02/28/2010");
		Date dataEntregaInicial = null;
		Date dataEntregaFinal = null;
		List lista = new ArrayList();
		String idFornecedor = null;
		
		voc.addParameter("valorInicial", null);
		voc.addParameter("valorFinal", null);
		voc.addParameter("dataEmissaoInicial", dataInicial);
		voc.addParameter("dataEmissaoFinal", dataFinal);
		voc.addParameter("dataEntregaInicial", dataEntregaInicial);
		voc.addParameter("dataEntregaFinal", dataEntregaFinal);
		voc.addParameter("idFornecedor", idFornecedor);
		
		listaRetorno = new PaginatedList(lista, 1000, paginationCriteria);
	}

	/*
	 * Verifica se quando chamar o método findNative passando null
	 * apenas no primeiro parâmetro vai apontar erro de NullPointerException
	 * 
	 * Resultado Esperado: NullPointerException
	 */
	@Test
	public final void testFindNative() {
		listaRetorno = bean.findNative(paginationCriteria, voc);
	}

}

Se alguém tiver alguma dica ou algum exemplo mais complexo e mais próximo da realidade que apresento agradeço.

3 Respostas

F

cara teu primeiro passo é criar um mock do metodo

findByNativeQuery(query.toString(), parameters);

para ele retornar o resultado esperado.

Posso saber o por que de testar essa informação?

Você não deve testar consultas no banco a não ser que essa consulta nunca mude, não é vantagem ficar tando manutenção em um teste que quebra a cada compilação.

G

Primeiro, onde acho algum manual de como criar mocks de métodos?

Ai que vem o problema, eu entrei recentemente em uma empresa que não tinha o costume de promover testes unitários.
Me deram a missão de iniciar a implementação deles e me veio a pergunta, “Por onde começar a implementar testes?”

Como o sistema esta “estável” pensei em começar pelas consultas chave. Aqueles pontos que não podem haver rupturas em momento algum…

Mas se tiver alguma ideia melhor estou aberto a sugestões.

F

Questão que vc deve pensar é essa:

Esse sistema foi feito para ser testado?

Para se usar testes unitarios deve-se usar a metodologia TDD baseada no teste, é muito dificil pegar um sistema que não foi projeto para isso e implementar os testes.

Eu gosto de usar o Mockito para os testes, é bem simples e facil de ser usado.

Por exemplo Para testar essa consulta chave que não pode falhar. Qual seria o criterio esperado para ela não falhar? o Tamanho maior que 0? Não ser gerada exception?
Mesmo assim são testes simples, e não avaliam corretamente o metodo.

Partindo do principio do TDD, para um determinada entrada teremos uma única saída.
É assim que deve funcionar, o que foi variavel se torna complicado de testar, por exemplo entrando a String “Joao”, deve retornar os joãos cadastrados. mas quantos joãos podem ter? o Ideal era simular a base com alguns joaos la dentro e ver se o retorno é o mesmo.

vou falar do mock com o Mockito, para adapta-lo para o Easymock não deve ser complicado

import static org.mockito.Mockito.*;

Qualquer qualquer = mock(Qualquer.class);
when(qualquer.getNome()).thenReturn("Teste");//o Metodo getNome ira retornar sempre "Teste"
ClasseTeste teste = new ClasseTeste (qualquer);

Se tiver alguma duvida posta ai que a gente ajuda.

Criado 24 de fevereiro de 2010
Ultima resposta 24 de fev. de 2010
Respostas 3
Participantes 2