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.

Tags: , , , , ,

5 Responses to “Mock Objects em excesso podem atrapalhar”

  1. Eu também acho que esta é a melhor abordagem.

    Sempre procuro utilizar mock ou stub em coisas mais lentas (rede ou um maior processamento) nas outras situações prefiro utilizar um objeto “verdadeiro”. Isto não é regra, depende da classe também que irei testar… é uma questão de feeling :P

    Isso traz uma clara desvantagem que é a redução do isolamento do teste, mas traz um benefício também que ao fazer um teste da classe B que utiliza A, você pode testar um comportamento de A que havia esquecido.

  2. Carlos Alexandre says:

    Eu também acho Mock Objects melhor aproveitado nas dependências entre camadas. Como uma definiçaõ mesmo dos limities de forma clara. Como você disse, existem situações onde mocks se tornam contra-produtivos e eu citaria a implementação de um modelo de objetos onde há mais dependências e comportamentos para serem verificados, nesses casos eu prefiro usar objetos falsos e validação de estado.

    O ideal é acomodar essas diferentes situações no mesmo projeto.

  3. [...] claro que Mock Objects em excesso podem atrapalhar, mas é tudo uma questão de bom senso: costumo dizer para quem esta começando a focar os testes [...]

  4. lookyller says:

    Galera concordo plenamente que em muitas situações é complicado realmente aplicar um Teste Unitário isolando todas as dependências, por intermédio de Mock Objects.
    No entanto, acredito também que essa complexidade se deve na maioria das vezes a uma falha de projeto, e não somente a questão do aplicar ou não?

    Será que o projeto ou até mesmo a arquitetura adota não teria que ser revista? Se há muitas dependências na unidade testada, com certeza tem algo de errado por trás.

    A minha opinião é que cada tipo de Teste aplicado tem seus objetivos bem idealizados e por consequência, se adotado uma abordagem já integrada na geração dos testes, alguns defeitos exercitados apenas em situações isoladas poderiam passar desapercebidos e vice-versa.

    Seria interessante analisar a melhor situação e é claro, o nível de cobertura disposto a atingir.

Leave a Reply