Stubs são classes que simulam o comportamento de classes mais complexas através de uma implementação simples. Com eles é possível isolar a classe testada do resto do sistema, simplificando os testes e deixando-os mais independentes.
Exemplo: usando Stubs para testar Servlets
Para ver como criar stubs que facilitam os testes, veja este exemplo de um servlet de Hello World, utilizando recursos como passagem de parâmetros e sessão. Começamos escrevendo nosso primeiro teste:
public void testService() throws ServletException, IOException
{
ServletHelloWorld servlet = new ServletHelloWorld();
// criando stubs
StubHttpServletRequest request = new StubHttpServletRequest();
StubHttpServletResponse response = new StubHttpServletResponse();
// chamando servlet
servlet.service(request, response);
// verificando resultados
String mensagem = (String) request.getSession().getAttribute("mensagem");
assertNotNull("Deveria haver uma mensagem na sessão", mensagem);
assertEquals("Hello World", mensagem);
}
Nosso objetivo aqui é ignorar a existência de um container web (Tomcat, por exemplo) e mesmo assim queremos avaliar o comportamento do servlet. Para isso, criamos três classes implementando as respectivas interfaces da API de servlets:
public class StubHttpServletRequest implements HttpServletRequest
public class StubHttpServletResponse implements HttpServletResponse
public class StubHttpSession implements HttpSession
Uma vez criadas estas classes, podemos também criar o nosso servlet:
public class ServletHelloWorld extends HttpServlet
{
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
}
}
Todo código compila agora, e podemos começar a rodar os testes. O primeiro problema que surge é um NullPointerException ao tentar buscar a sessão do request, portanto, vamos evoluir as classe StubHttpServletRequest e StubHttpSession:
public class StubHttpServletRequest implements HttpServletRequest
{
StubHttpSession session = new StubHttpSession();
public HttpSession getSession()
{
return session;
}
....
}
public class StubHttpSession implements HttpSession
{
Map attributes = new HashMap();
public Object getAttribute(String arg0)
{
return attributes.get(arg0);
}
public void setAttribute(String arg0, Object arg1)
{
attributes.put(arg0, arg1);
}
...
}
Agora podemos rodar o teste novamente e verificar que um assert falha (“Deveria haver uma mensagem na sessão”). Isto significa que podemos finalmente implementar nosso servlet:
public class ServletHelloWorld extends HttpServlet
{
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
request.getSession().setAttribute("mensagem", "Hello World");
}
}
A partir de então nosso teste passa. Podemos evoluir nosso servlet, usando uma passagem de um parâmetro a ser guardado junto com a mensagem. Para isso, criamos um novo teste:
public void testServiceComParametro() throws ServletException, IOException
{
ServletHelloWorld servlet = new ServletHelloWorld();
// criando stubs
StubHttpServletRequest request = new StubHttpServletRequest();
StubHttpServletResponse response = new StubHttpServletResponse();
// definindo parâmetro a ser passado para o servlet
request.setupGetParameter("nome", "João");
// chamando servlet
servlet.service(request, response);
// verificando resultados
String mensagem = (String) request.getSession().getAttribute("mensagem");
assertNotNull("Deveria haver uma mensagem na sessão", mensagem);
assertEquals("Hello João", mensagem);
}
Observe que agora precisamos criar um método setupGetParameter que não existe na interface HttpServletRequest. Porém, ele que permite que deixemos o stub no estado correto para que o servlet o acesse. Aqui está o novo trecho inserido na classe StubHttpServletRequest:
Map parameters = new HashMap();
public void setupGetParameter(String name, String value)
{
parameters.put(name, value);
}
public String getParameter(String arg0)
{
return (String)parameters.get(arg0);
}
Mais uma vez temos um assert que falha, já que a lógica não foi definida no servlet. Então fazemos a alteração no método service:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String nome = "World";
String parametro = request.getParameter("nome");
if (parametro != null)
{
nome = parametro;
}
request.getSession().setAttribute("mensagem", "Hello " + nome);
}
Finalmente, todos os testes passam e ficamos satisfeitos. Conseguimos testar nosso servlet e começamos a criar uma implementação simples dos recursos do container web para ser reaproveitado nos nossos próximos testes.