Categories
Notícias Testes

Livro promissor sobre mock objects

Steve Freeman e Nat Pryce do JMock, um dos meus projetos favoritos, estão escrevendo um livro entitulado “Growing Object-Oriented Software, Guided by Tests”. O assunto é muito bom e conhecendo os caras e os materiais que eles já publicaram (especialmente o artigo que fala sobre a experiência deles evoluindo uma DSL, baseando-se no desenvolvimento do JMock – “Evolving an Embedded Domain-Specific Language in Java”), acho que o livro promete.

O primeiro capítulo já está disponível no blog do JMock e chama-se “What’s the point of Test-Driven Development?”. A leitura é obrigatória e já dá uma pista do que está por vir.

Categories
Integração Contínua TDD Testes

Mock Objects em excesso podem atrapalhar

Acabo de ler na Artima um artigo sobre o uso excessivo de Mock Objects.

Fazer testes unitários pode não ser a tarefa mais fácil do mundo quando suas classes dependem de sistemas externos que você não controla como banco de dados, webservices e qualquer outra coisa que não faz parte do seu sistema. É aí que entram os Mock Objects, que são objetos que servem para “simular” as dependências das suas classes. Eles possuem comportamento controlado e fazem exatamente o que você definir, tornando os resultados das chamadas às dependências de um código totalmente previsíveis. Sabendo que todas as dependências estão funcionando corretamente, qualquer falha que aconteça nos testes está com certeza no local (método, classe, etc) testado.

O problema é quando decide-se simular todas as dependências. Isso é um pouco controverso porque na verdade quando você está fazendo testes unitários o certo mesmo é isolar o método e “mockar” todas as dependências. Porém em alguns casos isso acaba fazendo com que o teste fique muito complexo e difícil de ser entendido e mantido.

Além disso os testes com muitos Mocks podem acabar ocultando problemas na colaboração entre os objetos. Os objetos dependentes em uma determinada situação podem funcionar diferente de como foram “mockados” e pode ser interessante utilizar os objetos reais. Mas neste caso os seus testes seriam testes de integração e não testes unitários.

Ultimamente eu tenho optado por ir pelo caminho do meio e por isso concordo quase integralmente com a opinião do Alex Ruiz. Acredito que em boa parte das vezes você não precisa criar mocks de tudo que vê pela frente.

Um exemplo real é o sistema que estou trabalhando atualmente, onde estou desenvolvendo um cliente para um webservice REST. Este cliente é bem magro e basicamente ele pega XMLs de coisas que foram processadas no servidor (webservice) e transforma em objetos Java. Para isso o cliente acessa via HTTP um determinado endereço, obtém um XML que representa uma entidade do sistema, transforma em um objeto Java e retorna o resultado. Como este cliente é muito magro e praticamente não faz nenhum processamento, na maioria dos testes a única dependência que eu “mockei” foi o XML retornado, já que a única coisa não controlada pelo meu sistema é o canal HTTP e o servidor dos webservices que pode estar a qualquer momento offline e meu teste não pode falhar por causa disso. Para fazer isso eu injetei no repositório de objetos um HTTP Client mock que sempre retorna um XML válido. Com isso o meu teste verifica se o cliente retorna objetos Java corretos considerando que o webservice está funcionando. É claro que este não é o único tipo de teste que eu faço, tenho testes mais específicos para outras funcionalidades mais importantes, como a classe que transforma objetos em XML para Java e por aí vai.

Resumindo isso tudo, acho importante analisar cada caso e ver se há necessidade de criar testes canônicamente corretos ou se opções mais simples podem resolver o problema da mesma forma.