Quando começamos com TDD (test-driven development) há uns anos,
na empresa em que trabalho, implementamos vários mocks na mão, declarando uma nova classe e
sobrescrevendo os comportamentos que queríamos “mockear”. Logo
percebemos que esse trabalho braçal poderia ser simplificado utilizando
frameworks de mock. O que não percebemos logo de cara é que os testes
com mock estavam ficando pouco legíveis e, ao mesmo tempo, quebrando com
muita facilidade. Por vezes, ao ler um teste tínhamos muita dificuldade
de responder rapidamente o que aquele teste assegurava. Mas por que isso
estava acontecendo?
Testes que verificam se um conjunto de métodos foram chamados
corretamente, com os parâmetros esperados, podem sofrer de “excesso de
expectativas”. O problema é que misturávamos situações em que queríamos
garantir que algo foi chamado (expectativa real) com a definição de
comportamentos via mock objects necessários para isolar o teste e
permitir que as dependências fossem satisfeitas. Essas últimas
“expectativas” não eram muito importantes. De fato não estávamos muito
interessadas nelas. Logo, nosso grande erro foi ao final dos testes
simplesmente chamar o mockRepository.VeryAll() do RhinoMock, por
exemplo.
Quando analisamos com cuidado cada teste, vemos que nem todos os
comportamentos definidos via expectativas mock são o fim. Algum são
apenas um meio para conseguirmos rodar tudo sem problemas. Logo, uma boa
estratégia é distinguir “Allow” de “Expect”. Ou seja, existem
comportamentos que devem ser definidos pois podem ser chamados, apesar
de não estarmos muito interessados neles. Esses são os “Allow”. Já os
“Excect” são aqueles comportamentos que realmente queremos monitorar,
pois eles implicam no sucesso ou não do teste em questão.
Alguns têm defendido uma abordagem mais radical, defendendo inclusive
que testes com mock não garantem que tudo está realmente funcionando,
como é o caso do Brian Swan na palestra “Mocks Suck”. Vale a pena
assistir e refletir sobre o assunto.
Mocks Suck (and what to do about it) – Brian Swan from Engine Yard on Vimeo.
Embora concorde pelo menos em parte que trabalhar com Mocks gera
alguns problemas, não consigo engolir bem a ideia defendida pelo Brian
de “sempre utilizar os objetos reais” pois, como ficou claro nas
perguntas ao final da palestra, ele precisa utilizar bancos de dados em
seus testes para que tudo seja executado de forma “real”.
Não vejo
problemas em construir testes de integração que utilizem os objetos
reais e até mesmo banco de dados. O problema pra mim é construir o
sistema sempre dependendo disso. TDD é uma técnica de construção de
software, e não de teste, e construir tendo tudo acoplado é bem ruim.
Poder isolar o que você está construído do restante utilizando mocks é
prático e eficiente, e não vejo motivo para abrir mão dessa facilidade.
Concluindo, concordo com o Brian que enfrentamos alguns desafios ao
trabalharmos com mocks, só não acho que a solução dada por ele seja a
resposta. E você, o que acha?