Teste unitário

Se você utiliza injeção de dependências através de seu construtor e seus parâmetros são enviados em seu método, fica bem simples criar testes unitários, por exemplo:

@Component("sum")
public class Sum {
        private int result;
        
        public void sum(int first, int second) {
                this.result = first + second;
        }
        
        public int getResult() {
                return this.result;
        }
}

public class SumTest extends TestCase {

        public void testSumsCorrectlyLowNumbers() {
                int expected = 1999;
                Sum logic = new Sum();
                logic.sum(1000, 999);
                assertEquals(expected, logic.getResult());
        }
        
}

Full browser testing

Você pode utilizar o Selenium para testar seu sistema completamente através de um broser específico.

Functional/Integration testing

Vraptor também tem focos no functional-testing das suas lógicas de negócios.

A maioria dos frameworks (Struts, Webwork etc.) exigem que os testes sejam feitos pelo programador: criar uma instância da classe , simular a mágica e chamar seu método!

Mas se você chamar o setter, não será a mesma coisa como usar um conversor! Veja outros exemplos:

  1. Struts extension for junit, verifique o tamanho do código necessário para fazer um simples forward!
  2. Struts example usando cactus, verifique o tamanho do código para fazer um simples teste!
  3. exemplo de Spring

    A maioria dos exemplos anteriores foram escritos por causa da falta de convenções (como o arquivo struts-config.xml, que pode ser alterado)...

A escolha do VRaptor

O TestEngine do Vraptor simula o ambiente de testes e podemos testar as nossas lógicas de negócios integradas com o mesmo (testes de integração ou funcionais).

Criação da classe de teste

Vamos escrever uma classe de teste chamada TestPersonLogic para testar o tutorial de validação.

Por dentro, vamos criar o TestEngine, mas cuidado: todos os arquivos xml serão carregados e por isso seria uma boa idéia não fazer isso mais de uma vez (de bom senso):

public class TestPersonLogic extends TestCase {

        private static final TestEngine ENGINE = TestEngine.createEngine(
                                        new MockedServletContext("WebContent"));
}

O MockedServletContext é um contexto de mentira para o TestEngine poder simular o contexto de servlets. Passe o nome da sua pasta web como argumento, no nosso caso WebContent.

Seqüência da requisição

Um teste funcional necessita de uma ou mais requisições, então testes mais avançados estão disponíveis (com sessão e tudo mais).

Para criar uma sessão (a mesma coisa como você fosse abrir o browser, uma sessão http) use:

                TestSession session = ENGINE.createSession();

Uma simples requisição válida

Uma requisição válida para nosso exemplo deveria chamar a lógica person.add.logic com os parâmetros person.name=Guilherme, person.address=Vergueiro e person.preferredNumber=5.

Então como chamaria exatamente essa requisição?

                String result = session.execute("person.add.logic",
                                "person.name=Guilherme", "person.address=Vergueiro",
                                "person.preferredNumber=5");

Vamos afirmar o retorno ok (ou null, lembre-se: o valor padrão de returno é ok):

                assertEquals("ok",result);

O resultado

A classe final para testar o resultado ok é:

package org.vraptor.examples.first;

import junit.framework.TestCase;

import org.vraptor.Result;
import org.vraptor.VRaptorException;
import org.vraptor.test.TestEngine;
import org.vraptor.test.TestSession;

public class TestPersonLogic extends TestCase {

        private static final TestEngine ENGINE = TestEngine.createEngine();

        public void testAddsANewPerson() throws VRaptorException {
                TestSession session = ENGINE.createSession();
                Result result = session.execute("person.add.logic",
                                "person.name=Guilherme", "person.address=Vergueiro",
                                "person.preferredNumber=5");
                assert result.getReturnCode().equals("ok");
        }

}

Erros de validação

Vamos continuar e testar a validação (continua aqui depois você fez o tutorial de validação):

Se nós mandarmos somente dois parâmetros, a lógica deverá retornar invalid, então vamos tentar:

        public void testComplainsAboutNameError() throws VRaptorException {
                TestSession session = ENGINE.createSession();
                String result = session.execute("person.add.logic",
                                "person.address=Vergueiro", "person.preferredNumber=5");
                assertEquals("invalid",result);
        }

        public void testComplainsAboutAddressError() throws VRaptorException {
                TestSession session = ENGINE.createSession();
                String result = session.execute("person.add.logic",
                                "person.name=Guilherme", "person.preferredNumber=5");
                assertEquals("invalid",result);
        }

        public void testComplainsAboutNumberError() throws VRaptorException {
                TestSession session = ENGINE.createSession();
                String result = session.execute("person.add.logic",
                                "person.name=Guilherme", "person.address=Vergueiro");
                assertEquals("invalid",result);
        }

Diretório de saída separado

É importante que você separe a pasta para o output das suas classes de testes do output das classes da sua aplicação. Senão Vraptor's class loader entra no conflito com o TestEngine e sua aplicação não iniciará.