No primeiro artigo desta série, dei uma breve introdução dos Dublês de Testes (http://www.bluesoft.com.br/dubles-de-testes/). Neste artigo, vou demonstrar como aplicar esta técnica utilizando uma das variações: Dummy Object.
Este tipo de dublê é usado apenas para que a execução do teste seja possível, ou seja, não interage com a unidade testada, mas precisa existir para que o teste seja bem sucedido. A grande vantagem de utilizar este tipo de dublê é não precisar criar uma série de objetos que não serão testados. Observe abaixo.
Dummy1
Neste exemplo, uma Nota Fiscal possui vários itens, e cada item está vinculado a um produto qualquer. Suponha que seja necessário testar o método que adiciona um item na nota e que o construtor da Nota Fiscal exija um Cliente, que precisa ter um Endereço, que precisa ter uma Cidade, que precisa ter um Estado. O objeto Cliente e suas dependências não são alvos do teste, mas sem eles não há como fazê-lo. Veja como ficaria o teste sem usar um dublê:

O Dummy é usado justamente para evitar este tipo de desperdício de código. Um objeto Dummy nada mais é que uma classe parecida com a original, mas sem comportamento. Dessa maneira é possível criar objetos de uma forma mais simples e que não necessitam de ter todas as suas implementações e dependências, como o caso do objeto Cliente, que necessita do objeto Endereco que por sua vez precisa da Cidade e assim por diante. Para que isto, faz-se necessário criar uma interface que será implementada pela classe Cliente e pelo dublê que o substituirá. Veja a interface (InterfaceCliente) e as classes (Cliente e ClienteDummy):

Com a interface sendo implementada pelo Dummy não será necessário criar todas as dependência da codificação real (EnderecoCidade e Estado). Embora ClienteDummy substitua o objeto Cliente, ele não pode de maneira alguma ser chamado ou interagir com o teste. Se isto vier a acontecer, significa que ele não é o tipo de dublê indicado para o cenário em questão e o teste poderá ter um comportamento inesperado. Para garantir que esta interação não irá acontecer, nos métodos de ClienteDummy deve ser incluído um código que lança uma RuntimeException informando que algo de errado aconteceu. Veja como ficou o código de ClienteDummy:

Com o Dummy criado, não faz mais sentido preencher tantos objetos para testar o método adicionaItem() da Nota Fiscal.
Repare que antes era necessário preencher quatro objetos inúteis ao teste (Cliente, Endereco, Cidade e Estado) e todos eles foram substituídos por um Dummy (ClienteDummy).

Quer saber mais?

No próximo artigo desta série, veremos exemplos de Test Stub e Spy.
Até breve e bom código!

Autor

Ismael Soares é Gerente de Engenharia de Software na Bluesoft em São Paulo. É formado em banco de dados pela Faculdade Impacta de Tecnologia e possui mais de 14 anos com experiências em análise e desenvolvimento de sistemas. Já trabalhou com diversas tecnologias, entre elas: VB6, ASP, PHP, C#.NET, VB.NET, ASP.NET, PL/SQL, T-SQL, Groovy, Ruby e Java. Já participou de diversos projetos com banco de dados entre eles: Oracle, MSSQL Server, MySQL e Postgree.

4 Comentários

  1. A abordagem de utilizar dummy objects é válida, mas não gosto da ideia de ter que criar uma nova classe para representar o domínio que será utilizada somente nos testes.
    Uma maneira de solucionar esse problema sem utilizar dummy objects seria criar toda a estrutura do objeto, o que pode ser trabalhoso conforme você mesmo citou. Para isso sugiram os Test Data Builders, que são uma implementação de Builders para facilitar a criação dos dados utilizados nos testes. Gosto muito mais dessa abordagem por estar lidando com o objeto real do meu sistema e não uma outra classe utilizada somente nos testes.
    O pessoal da Amil, eu me incluo nesse grupo porque trabalhei um pouco lá rs., criou um framework para realizar essa tarefa de Test Data Builder, o nome dele é Fixture-Factory (https://github.com/six2six/fixture-factory). Ele disponibiliza API para facilitar a criação / organização / reutilização dos objetos e acrescenta alguns temperos a mais, como a possibilidade de gerar esses objetos e persistir eles na base de dados, facilitando a criação de testes de integração sem a necessidade de XMLs ou SQLs utilizados por frameworks como o DBUnit.
    O Aniche já publicou um post bem legal sobre o framework no blog da Caelum que gerou uns comentários bem legais (http://blog.caelum.com.br/criando-cenarios-de-teste-com-fixture-factory/)
    Abraço e parabéns pelo post!

    • Ismael Soares Resposta

      Obrigado limanykolas. Já testei o Fixture-Factory. Foi uma sacada muito boa, parabéns por compartilhar com a comunidade.

  2. Grande Ismael, tudo bem?
    Excelente artigo cara, parabéns!
    Gostaria de conversar a respeito de alguns pontos.
    Uma vez que seu teste não vai interagir com a dependência que tal passar um null? Assim fica explicito que aquela dependência não é exercitada naquele cenário, além de não termos que criar uma interface para uma entidade simples, e também uma implementação dummy. O que acha?
    Grande abraço!

    • Ismael Soares Resposta

      Olá Renan, obrigado pelo feedback.
      Sim, você poderia passar null. No entanto, se por algum equivoco você tentasse interagir com o objeto durante a execução do teste, receberia um NullPointer. Se você usar o Dummy Object e isto acontecesse, recebei uma exception “mais amigável”. Quanto a criação das intefaces, é opcional. Eu costumo apenas herdar a classe original e sobrescrever os métodos que não podem ser chamados com uma exeçeção amigável.
      http://xunitpatterns.com/Dummy%20Object.html

Deixe aqui o seu comentário