Component Tests

The most important kind of tests for any Tapestry application will probably be those covering Page / Component classes. This library also provides some conveniences for those kinds of tests.

In this example we'll take a look at how one of the core Tapestry components is tested using a couple of tricks provided by this library - Button. This is a simple Form component that renders an html button block like:

<button type="button" name="updateForm">Submit</button>

To get us started we'll jump right in to a real world example of testing the rendering logic of the Button component. The full source for this test can be found here. The source of the actual button component itself can also be found here.

...
import org.apache.tapestry.BaseComponentTestCase;
import org.testng.annotations.Test;

@Test
public class TestButton extends BaseComponentTestCase
{
    public void testRender()
    {
        Button b = newInstance(Button.class, "name", "assignedName");

        IMarkupWriter writer = newBufferWriter();
        IRequestCycle cycle = newCycle();

        replay();

        b.renderFormComponent(writer, cycle);

        verify();

        assertBuffer("<button type=\"button\" name=\"assignedName\"></button>");
    }
}

The following sections will expand further on each part of the test used.

BaseComponentTestCase

In almost all of the core Taptestry test cases BaseComponentTestCase is the actual test class extended. It provides a number of additional conveniences not found in the basic TestBase class - such as being able to create a buffered IMarkupWriter instance that allows you to check the string produced from a component render instead of having to do mock calls for all of the method invocations on a mock IMarkupWriter object.

The example above makes use of this method with the following lines:

    ...
    IMarkupWriter writer = newBufferWriter();

    ..

    assertBuffer("<button type=\"button\" name=\"assignedName\"></button>");

You will find many other small convenience methods, such as various trainDoFoo() methods which do some of the grunt work of training a mock object for common things like getting a ILink object from an engine service.

newInstance(Class class, Object...arguments)

This is really probably the most important method for everyones tests. What it does is allows you to create a real object instance of any component / page class along with a pre-configured set of properties for your abstract getter/setter methods.

The example above did this with the Button component by giving it a default value for the name property. The Button component inherits the getName()/setName(String name) methods from the AbstractFormComponent class - like all Tapestry form based components do.

The key to understanding how to use newInstance() is that you must pass in a name and value for each property you want to set on your page / component. The method has a varargs definition so you can pass in as many properties as you like. For instance - if you had another hypothetical form component with a simple Date value getter/setter you could create it like this:

...
    public void test_TestField_Render()
    {
        TextField field = newInstance(TextField.class,
                                        "name", "simple",
                                        "value", new java.util.Date(),
                                        "clientId", "simple");

        assert field.getValue() != null;
        assert java.util.Date.class.isInstance(field.getValue());
    }