Coding Dojo Floripa

Desenvolvimento Ágil

Trabalhando com Stubs

Posted by Ivan Sanchez em Terça-feira, Outubro 17, 2006

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.

3 Respostas to “Trabalhando com Stubs”

  1. […] Se usássemos mocks ao invés de stubs no nosso exemplo de stubs, teríamos algo como: […]

  2. Nessas horas que fica claro porque o Struts não é interessante para um sistema que visa ser feito com testes, pois ele acopla totalmente sua Action à HTTPRequest, criando a necessidade de usarmos Stubs. Frameworks como o VRaptor permite a criação de “actions” totalmente independentes do container web, facilitando (e muito) os testes.

  3. […] Trabalhando com stubs […]

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

 
%d bloggers like this: