Tuesday, June 1, 2010

Writing unit tests for Guice and Wicket

There are excellent frameworks out there for bringing the Guice power into your JUnit tests, like AtUnit or GuiceBerry, however, for the sake of simplicity, this post builds upon a simple Test Runner class described in another post written in 2008 by Gili Tzabari about Guice and JUnit4 integration.

Here is a very simple MyGuiceTestRunner implementation:
public class MyGuiceTestRunner extends GuiceTestRunner {
 public MyGuiceTestRunner(Class<?> classToRun) throws InitializationError {
  super(classToRun, new WebModule(), new MyModule(), new HibernateModule());
 }
}
And here is an abstract wicket test to ease our work later:
@RunWith(MyGuiceTestRunner.class)
public class AbstractWicketTest {
 
 private final WicketTester wicketTester;
 
 protected final WicketTester getWicketTester() {
  return wicketTester;
 }

 public AbstractWicketTest(Injector injector) {
  wicketTester = new WicketTester();
  WebApplication app = wicketTester.getApplication();
  app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
 }
}
Some points of intrest in this implementation:
  • Class is annotated with @RunWith, this tells JUnit to use MyGuiceTestRunner to run this test (and subclasses too).
  • In the constructor we create a WicketTester which in turn will create a dummy wicket web application for us (BaseWicketTester.DummyWebApplication is the exact type). If we need a custom application we could simply use other WicketTester constructors that take an Application instance and use it instead of the inner dummy one.
  • Once a WicketTester instance was created, we add attach a GuiceComponentInjector just like we would in a normal guicey wicket web application.
In a typical test subclass of AbstractWicketTest we get a reference to the injector using constructor injection (remember this test is injectable because it is being run by MyGuiceTestRunner):
public class SampleWicketTest extends AbstractWicketTest {
 
 @Inject
 public SampleWicketTest(Injector injector) {
  super(injector);
 }

 @Test
 public void test() {
  WicketTester wicketTester = getWicketTester();
  wicketTester.startPage(TestPage.class);
  wicketTester.assertRenderedPage(TestPage.class);
  wicketTester.assertLabel("meow", "Testing 1 2 3");
 }
}
For the sake of completeness, here is the code for the test page itself (html markup omitted):
public class TestPage extends WebPage { 
 
 @Inject private IService service;
 
 public TestPage() {
  add(new Label("meow", "Testing 1 2 3"));
  service.doSomething();
 } 
}
Thats it, you are now free to write Guice powered tests for your Guicey Wicket pages.

Enjoy :-)

No comments:

Post a Comment