VRaptor

Testing Components and Controllers

To do unit tests with VRaptor 4 is often simple, which isn’t so different from unit tests of any class.

CDI takes care of your application’s Dependency Injection (DI) and to improve the testability of your class, we advise the dependency injection by constructor, thus you may work easily with mocks, such as:

@Controller
public class PersonController {

    private final Result result;

    private final Validator validator;

    /**
     * @deprecated CDI eyes only
     */
    protected PersonController() {
        this(null, null);
    }

    @Inject
    public PersonController(Result result, Validator validator) {
        this.result = result;
        this.validator = validator;
    }

}

MockResult and MockValidator classes will help you to test your VRaptor’s Controller:

public class PersonControllerTest {

    private MockResult result;
    private MockValidator validator;
    private PersonController controller;
    
    @Before
    public void setUp() {
        result = new MockResult();
        validator = new MockValidator();
        controller = new PersonController(result, validator);
    }
    
}

If you use field injection Junit by itself will not provide the CDI dependencies for you, since it do not start CDI context. However there are a lot of solutions to help you with that, i.e Arquilian.

Result and Validator are components almost always present in your Controllers, to make your tests easier, VRaptor provides mocks for these implementations.

MockResult

The MockResult ignores the redirecting that you do, and collects the included objects, so you can inspect them and make your assertions.

Consider the following PersonController’s method:

@Post("/person/add")
public void add(Person person) {
    validator.addIf(person.getName() == null, new SimpleMessage("name", "The name should be filled."));
    validator.onErrorRedirectTo(IndexController.class).index();

    result.include("success", "Successfully added.");
    
    result.redirectTo(IndexController.class).index();
}

To test it you can use on your class PersonControllerTest something like:

@Test
public void shouldHaveSuccessMessage() {
    Person person = new Person();
    person.setName("Renan Montenegro");
    
    controller.add(person);
    
    Assert.assertTrue(result.included().containsKey("success"));
    Assert.assertEquals("Successfully added.", result.included("success"));
}

Note that any call of the type result.use(...) will be ignored.

MockSerializationResult

In a similar way, you can use the MockSerializationResult anytime you want to inspect the serialized content in Result.

In your PersonControllerTest class the result should have the type MockSerializationResult, like this:

private MockSerializationResult result;

Consider the following PersonController’s method:

@Post("/person/serialize")
public void serialize(Person person) {
    result.use(Results.json()).from(person).serialize();
}

In your test you can do something like:

@Test
public void shouldSerializePerson() {
    Person person = new Person();
    person.setName("Renan Montenegro");
    
    controller.serialize(person);
    
    Assert.assertEquals("{\"person\": {\"name\": \"Renan Montenegro\"}}", result.serializedResult());
}

MockValidator

The MockValidator will execute the validation accumulating possible errors. To retrieve them you can use the method getErrors() as you can see in the example:

@Test
public void shouldThrowValidationException() {
    try {
        controller.add(new Person());
        Assert.fail();
    } catch (ValidationException e) {
        List<Message> errors = e.getErrors();
        Assert.assertTrue(errors.contains(new SimpleMessage("name", "The name should be filled.")));
        Assert.assertEquals(1, errors.size());
    }
}

The calling of the method validator.onErrorUse, in case of validation problem, will generate a ValidationException, that can be used as an expected result by your test, as the following:

@Test(expected = ValidationException.class)
public void shouldThrowValidationException() {
    controller.add(new Person());
}