Mocks vs Stubs: qual a diferença afinal?
Publicado por Ivan Sanchez em Sexta-feira, Outubro 20, 2006
Mock Objects representam uma abordagem para simular objetos dentro dos testes. Isso nos ajuda quando o objeto real é muito complexo, lento ou ainda nem existe. Até este ponto mocks são bem parecidos com stubs. A diferença entre eles está nas abordagens que eles propõem:
- Com stubs, nos preocupamos em testar o estado dos objetos após a execução do método. Neste caso incluimos os asserts para ver se o método nos levou ao estado que esperamos.
- Com mocks, a preocupação é testar a interação entre objetos durante a execução do método. Neste caso, os asserts servem para ver se os métodos se relacionaram como o esperado.
Exemplo: usando Mocks para testar Servlets
Se usássemos mocks ao invés de stubs no nosso exemplo de stubs, teríamos algo como:
import static org.easymock.EasyMock.*;
public class ServletHelloWorldTest extends TestCase
{
public void testService() throws ServletException, IOException
{
ServletHelloWorld servlet = new ServletHelloWorld();
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
HttpSession session = createMock(HttpSession.class);
expect(request.getParameter("nome")).andReturn(null);
expect(request.getSession()).andReturn(session);
replay(request);
session.setAttribute("mensagem", "Hello World");
replay(session);
servlet.service(request, response);
verify(request);
verify(session);
}
public void testServiceComParametro() throws ServletException, IOException
{
ServletHelloWorld servlet = new ServletHelloWorld();
HttpServletRequest request = createMock(HttpServletRequest.class);
HttpServletResponse response = createMock(HttpServletResponse.class);
HttpSession session = createMock(HttpSession.class);
expect(request.getParameter("nome")).andReturn("João");
expect(request.getSession()).andReturn(session);
replay(request);
session.setAttribute("mensagem", "Hello João");
replay(session);
servlet.service(request, response);
verify(request);
verify(session);
}
}
Neste exemplo usamos o framework EasyMock que permite gerar os objetos mocks dentro dos testes, sem necessidade de implementar classes adicionais. Percebam que no teste, seguimos os seguintes passos:
- Criamos os mocks todos da mesma maneira, utilizando o comando createMock().
- Após a sua criação,utilizamos o método expect() para definir o comportamento que os métodos do mock terão ao serem invocados.
- Depois, usamos o replay() para indicar que os mocks estão prontos para uso e,
- Finalmente deixamos que o próprio framework verifique se a interação entre o objeto testado e o mock ocorreu como o esperado, através do método verify().
Desta forma conseguimos testar com a mesma eficiência dos stubs, mas com a vantagem de não precisarmos implementar nenhuma classe extra. Este também é o motivo que normalmente utilizamos stubs apenas quando estes são necessários, enquanto os mocks podem ser utilizados largamente nos testes quando queremos aumentar o isolamento entre as classes que estão sendo testadas.