Tuesday, April 8, 2008

Click supports functional and unit testing!

One of the first features completed for the upcoming 1.5 release, was to revamp the mock package and add functional and unit testing support. There is no need to extend any classes or override methods. Testing works out of the box.

For testing purposes there are two classes of interest: MockContainer and MockContext.
(Since 1.5 has not yet publicly available I will just refer to the actual source code)

Which class to use depends on what you want to test.

If you want to test your pages (functional tests) use the MockContainer which simulates a servlet container such as Tomcat or Jetty. With the container one will be enable to mock page requests, form submissions, file uploads, navigation etc.

In order to use MockContainer you need to specify a web directory where the container can find resources such as javascript, stylesheets and images. The easiest way to achieve this is to point the container to your project's web directory.

Example usage:

public class IntegrationTest extends TestCase {
    public void testFirstPage() {
        // Specify the project web directory for example: 'c:/dev/web'
        MockContainer container = new MockContainer("c:/dev/web");

        // Bootstrap the container
        container.start();

        // Set a request parameter
        container.setParameter("myparam", "Some parameter");

        // Simulate a user requesting the page, FirstPage. FirstPage will forward to SecondPage.
        FirstPage page = (FirstPage) container.testPage(FirstPage.class);

        // Assert that FirstPage does indeed forward to SecondPage
        Assert.assertTrue(container.getForwardPageClass(), SecondPage.class);

        container.stop();
    }
}
MockContext on the other hand is useful for testing custom controls (components).

Note that it is not necessary to specify a web directory when using MockContext.

Example usage:
public class ValidationFieldTest extends TestCase {

    public void testValidationField() {

        // Initialize the context.
        MockContext context = MockContext.initContext();

        int maxLength = 10;
        String fieldName = "name";
        ValidationField field = new ValidationField(fieldName, maxLength);

        // Retrieve the request and set field request parameter.
        MockRequest request = context.getMockRequest();
        request.setParameter(fieldName, "value");

        // onProcess binds the request attribute and field value
        assertTrue(textField.onProcess());

        // Assert that the field is still valid.
        assertTrue(textField.isValid());
    }
}
That is all there is to it.

The API is still evolving and feedback is appreciated. Our mailing lists are available here: