Monday, April 13, 2009

Tapestry 5 PageTester with Spring Managed Beans

In pursuit of better test coverage I have been looking into the Tapestry 5 PageTester. However, if you have services that are managed by Spring your pages that have these services injected will run into problems. In a normal Tapestry 5 app that using Spring managed beans the Spring context is loaded via the web ContextLoaderListener. These beans are then picked up by the Tapestry IOC for injecting into your pages. The PageTester doesn't perform this Spring context loading and therefore your injected services will be null. Furthermore, I'm only looking at unit testing here, so I don't want to fire up a bunch of integration type objects. For integration testing look at jitr.org A solution to the lack of Spring beans was to use a TestAppModule class that binds mock services for the PageTester to use.
new PageTester("domfarr.web.tapestry", "",
        "src/main/webapp", TestAppModule.class);
TestAppModule class looks like this.
  public static class TestAppModule {
    public static ContactService buildContactService() {
      return mock(ContactService.class);
    }
  }
I use Mockito as my mocking framework. The PageTester uses the TestAppModule to register my mock contact service and inject it into my page, and the tests have access to the contact service mock object by calling getService("ContactService") on the PageTester's registry.
  @Test
  public void testContactForm() {
    setupMockStubCalls();
    
    Element contactAddForm = startPage.getElementById("form");

    Map<String, String> formValues = new HashMap<String, String>();
    formValues.put("phoneNumber", "555-1234");
    formValues.put("fullName", "Dom Farr");
    
    Document submissionReturnDocument = pageTester.submitForm(
        contactAddForm, formValues);

    Element pageMessage = submissionReturnDocument
        .getElementById("message");

    assertThat(pageMessage.getChildMarkup(),
        equalTo("Contact Dom Farr Added Successfully"));
  }

  private void setupMockStubCalls() {
    ContactService mockContactService = pageTester.getRegistry().getService(ContactService.class);
    
    Contact contact = new Contact();
    contact.setFullName("Dom Farr");
    contact.setPhoneNumber("555-1234");
    when(mockContactService.save(contact).thenReturn(contact);
  }

0 comments:

Post a Comment