.NET

31 jul, 2009

Testes unitários na prática com Spring, TestNG, Mockito e Maven 2 – Parte 01

Publicidade

É possível criar testes unitários para aplicações desenvolvidas com Spring usando o TestNG.
Usando um  framework para mocks chamado Mockito, também é possível simular o comportamento de certos objetos para realizar o
testes. Ao final do artigo, rodaremos estes testes com o Maven.

Testes unitários com o TestNG

O
testNG é um framework para testes unitários feito em Java para Java :).
A solução é bem mais flexível do que o JUnit, que é a solução mais
tradicional de testes unitários em Java. O testNG provê mais
facilidades do que o JUnit
principalmente quando realizamos testes em grupos, esta funcionalidade
é útil para testar grupos de funcionalidades ou requisitos específicos.

Para uma comparação detalhada que vai de encontro à superioridade do testNG (confira este link),
vou utilizar os recursos de integração do testNG com Spring. Vamos ver
como injetar beans para testes e como utilizar o Mockito nos testes.

Mocks com o Mockito

Mockito
é um excelente solução para mock objects. Porque além de muito
simples, você trabalha com uma DSL muito focada e expressiva. O Mockito
facilita muito a nossa vida porque podemos criar os mocks direto nos
testes unitários evitado a necessidade de criar outras classes.

Claro
que, se necessário, podemos criar classes para aproveitar os objetos
mocks, podemos fazer isto usando o Spring e injetar uma classe cheia de
mocks.

Estruturando os testes

Existem
várias formas de estruturarmos os nossos testes unitários. Eu acredito
que o melhor uso é quando temos um método para cada necessidade. Como
podemos realizar esta quebra? Das seguintes formas:

  • Um método por cenário, para quem usa casos de uso.
  • Um método por feature, para quem usa FDD, por exemplo.
  • Vários métodos por requisitos, no caso de uma metodologia tradicional como o RUP.
  • Os método são criados conforme o caso de teste do Analista de Testes, um por cenário.

E
assim por diante… Existem diversas outras estratégias que poderíamos
adotar. O TestNG nos permite aplicar diversas marcações em um
teste. Podemos dizer, por exemplo, que um método de testes serve para o
requisito funcional RF005 e a o caso de uso 10 cenário alternativo 3. Então, com os grupos de testes, podemos rodar os testes por
requisitos ou por casos de uso por exemplo.

Tudo isso ajuda na
hora de aplicar testes em cima de um conjunto de funcionalidades ou
requisitos, por exemplo, na hora de fazer o deploy. Uma boa prática é
rodar todos os testes sempre, a aplicação como um todo deve estar
sempre funcionando, mas podemos criar uma certa rastreabilidade dos
testes com os requisitos ou casos de uso.

Dependendo do projeto,
uma matriz de impacto ou rastreabilidade é suficiente, mas ter este
mapeamento nos testes ajuda a acelerar as coisas.

Usando TestNG com Mockito

Quando
criamos um teste unitário com o testNG é possível usar o Mockito para
os objetos do teste, bem como para as dependências de sua aplicação.
Desta maneira você consegue ter um isolamento total do seu código do
resto da aplicação. Ainda é possível ter o seu código mesmo com
dependências de outros pontos da aplicação que não estão prontos ainda.

Tudo junto na Prática

Vamos
a uma aplicação de exemplo que fiz com todas estas soluções. A
aplicação é fictícia e serve para mostrar a integração desta solução como
um todo e como usar o testNG com Spring e Mockito. Então sem mais
delongas vamos à aplicação.

Vamos supor que estamos
desenvolvendo uma solução de gestão de vendas de produtos para algum
segmento do mercado. Então no nosso domínio fictício existem as
seguintes entidades:

  • Produto
  • Item
  • Vendedor
  • Venda
  • Comissão

O
Produto representa um produto qualquer como um sapato ou meia. O Item
possui um Produto e um valor, bem como quantidade e preço. Você
poderia utilizar outro tipo de modelagem, mas este modelo permite
lidar com produtos promocionais e descontos em vendas de quantidades
elevadas.

O Vendedor é o responsável pela Venda. Neste modelo
poderíamos adicionar o Cliente, dados e entrega, forma de pagamento e
muito mais, deixei o modelo restrito para facilitar o entendimento dos
testes.

Por fim existe a Venda que contém uma lista de itens e
bem como um Vendedor. Você pode conferir isto no seguinte diagrama de
classes abaixo:

Diagrama de classes do modelo

Certo. Agora vamos aos serviços da aplicação. Esta aplicação poderia ter
vários serviços, por motivos de simplificação e foco, vou usar
apenas 2 serviços, sendo que um deles não foi implementado ainda:

  • ItemService
  • VendaService -> VendaServiceImpl

São
estes dois serviços acima. Sendo que o serviço ItemService ainda não
tem implementação e o Serviço de Vendas tem a implementação padrão
chamada VendaServiceImpl. A implementação do serviço de vendas depende
do serviço de itens, mas esta dependência é feita através das
interfaces(contratos). Confirma o seguinte diagrama de classes:

Diagrama de classes dos Serviços

Podemos
trabalhar com dois cenários. Imagine que você desenvolveu o serviço de
vendas, ou tem que desenvolver o mesmo, e o serviço de itens não está
pronto ainda. É possível tocar este desenvolvimento em paralelo, isto é
feito através do contrato dos serviços (interfaces) e ainda é possível
testar seu código mesmo sem o serviço de item estar pronto. Para isso
vamos usar o TestNG com o Mockito.

Em um segundo cenário, o
serviço de itens está pronto, mas a sua implementação foi feita por
outra pessoa e é muito duvidosa. Logo, você pode ter certeza de que o seu
código está ok ou se o problema é no serviço de itens. Você também
poderia usar o Mockito com o TestNG para isolar a aplicação e testar
somente esta parte.

No próximo artigo vamos mostrar os códigos desta
aplicação, além de discutir mais sobre teste unitários, Spring e
Mockito. Você pode baixar os diagramas que fiz no EA nesta url.

Abraços e até a próxima.