Estou fazendo dois trabalhos atualmente: sobre Mock Objects (como preparatório para Service Simulation, se tudo der certo) e sobre WSS. Por isso, e também para receber alguns inputs (que seriam muito bem vindos) vou postar algumas coisas da minha pesquisa aqui no blog. E nesse post explico o que são Mock Objects.
Mock Objects são objetos que simulam outros objetos. São principalmente usados em testes de unidade. Existem vários frameworks de Mock Objects mas pessoalmente prefiro o jMock. Abaixo mostro um exemplo de um teste de unidade usando-se TestNG 5.9 e jMock 2.5:
public class PublisherTest { private Mockery context = new Mockery(); public PublisherTest() { context = new Mockery(); // para podermos mockar uma classe context.setImposteriser(ClassImposteriser.INSTANCE); } @Test public void testOneSubscriberReceivesAMessage() { // configura mock Subscriber subscriber = context.mock(Subscriber.class); Expectations expect = new Expectations(); String message = "message"; // configura estado do objeto Publisher publisher = new Publisher(); publisher.add(subscriber); // expectativas expect.never(subscriber).receive(message); context.checking(expect); // executa publisher.publish(message); // verifica context.assertIsSatisfied(); } }
Usamos mocks em cenários onde precisamos testar um objeto que depende de outros. Qual o problema de dependências? O objetivo dos testes de unidade é testar objetos em isolado, mas se usássemos um Subscriber real erros nele poderiam fazer falhar o teste do Publisher (ver figura abaixo). Por isso usamos mocks.
![]() Teste usando-se objetos reais |
![]() Teste usando-se mocks |
Com mocks podemos não só substituir algum objeto, mas também controlar todas as interações que são feitas com ele: verificar chamadas de métodos, valores de parâmetros, definir valores de retorno, etc. No código acima estamos por exemplo esperando uma chamada ao método receive do subscriber.
Dito o objetivo que motivou a criação dessa técnica, existem outros que vieram a ser supridos por mocks:
- Abstrair camadas mais baixas do sistema, tanto por elas não estarem prontas quanto por querermos trabalhar offline.
- Centralizar a configuração de estado no próprio mock ao invés de espalhá-las pelos testes de unidade.
- Simular condições difíceis de reproduzir, como o lançamento de uma excessão mais esdrúxula ou um valor retorno raro.
- Verificar mais rapidamente quando um erro ocorre (fail fast), indicando em que passo do comportamento esperado foi errado ao invés de apenas dizer que o estado final do objeto não condiz com o esperado.
Algo muito interessante vindo do uso de mocks é o Need-Driven Development (NDD), mas não pretendo falar dele aqui. Quando sair meu trabalho disponibilizo no blog, mas quem tiver curiosidade pode me escrever, é sempre bom trocar idéias



eu adoro quando venho aqui. fico vendo um monte de coisa que nao entendo nada. poxa, não entendo nada de computadores, e sei la o que.
Olá Rafael, muito bom o seu post explicando a necessidade dos Mock’s.
Você sabe se existe alguma maneira de utilizar os @TransactionAttribute nos testes unitários? Não posso na minha implementação colocar um begin e comit manual (em.getTransaction().commit()). Coloquei um begin e commit no teste unitário envolvendo o método que precise de um commit, foi a única solução que encontrei.
Queria apenas utilizar as anotações e q fosse simulado pelo contaíner ou por um mock container, vi que o EB3Unit não provê nda disso, jmock tb não encontrei nada. Você sabe de algo nesse sentido?
@JEFFMOR
Cara, estou escrevendo justamente sobre isso: se pretendes fazer testes de unidade mesmo deverias mockar a UserTransaction. No caso, usar o @TransactionAttribute até te pouparia trabalho pois não havia nada a ser feito.
No caso de realmente quereres fazer um teste funcional, frameworks mocks não vão criar um ambiente EJB para ti, e realmente, a solução que arranjasse é única. Só te daria a dica de usar AOP, ao invés de envolver todos os métodos com um commit(). O AspectJ agora tá permitindo definição de pointcuts através de anotações, ai tu pode fazer algo do tipo:
call(@TransactionAttribute * projeto.testes..*.*(..));
e definir um around() para controle transacional. Desse modo poderias chamar teus métodos transacionais transparentemente.
Muito interessante o post, Rafael. Parabéns! Meus testes unitários ainda não passaram do JUnit
Rola de mockar um resultado de uma requisição a um web service?
Pow, já ouvi falar em TDD, BDD, DDD, agora NDD??? Que parada é essa?
[]s
@Flávio Alves
Dá sim, uma das aplicações de mocks é justamente prover um “fake” de um componente ainda não implementado. Mas ai o web service deve estar sendo acessado através de uma interface (ou até um classe concreta, o jMock pode usar manipulação bytecode).
Vou dedicar um post para escrever sobre estratégias de uso de mocks.
Sobre NDD, é uma variação do TDD usada pela corrente mockist para desenvolvimento top-down :p
Liu… experimente o http://mockito.org/ … é show. É o mais fácil de usar que eu achei.