Home > Wicket > WicketTestBase – base class for testing Wicket + Spring web applications

WicketTestBase – base class for testing Wicket + Spring web applications

When writing integration tests in Wicket, there are few initialization steps that need to be executed before actual testing:

  1. data initialization – tests often need static data in the database for each and every test method.
  2. tester initialization – tester is initialized with Application and Session object, given locale needs to be set, Spring injector needs to be pre-configured etc.
  3. helper class initialization

Putting those actions to some init method (annotated with @Before in JUnit) would be a good idea. However I thought that since those steps are done in every single test, smart thing to do is moving them up in class hierarchy into some super class.
This is how WicketTestBase was created. Base class for integration tests in Wicket + Spring applications. Let’s take a look at it:

public class WicketTestBase {

 @Autowired
 private ApplicationContext applicationContext;

 protected WicketTester tester;
 protected EnhancedWicketTester enhancedTester;
 protected Clicker clicker;
 protected Enterer enterer;
 protected FormFiller formFiller;
 (...)

WicketTestBase has six protected fields. Spring’s ApplicationContext is injected, other five fields (tester, enhanced tester and helper classes) need to be initialized for every test. All fields have protected access level,  thus they can be reached from test classes that will extend WicketTestBase.

If you haven’t heard about enhanced tester, then please follow this article. If Clicker, FormFiller and Enterer are new to you, then kindly check my article about readable tests.

public void init() {
 populateData();
 createTester();
 initHelpers();
}

Next we have the public init method. This method will be called with every test. Method populateData is empty by default, but can be extended in test classes inheriting from WicketTestBase.

 /**
  * Override to populate data in database
  * for each test
  */
 protected void populateData() {
     // override in test if necessary
 }

Method createTester is the most complex one, but still it should be clear what it does.

private void createTester() {
 tester = new WicketTester((WebApplication)
 applicationContext.getBean("wicketApplication"));
 tester.setupRequestAndResponse();
 tester.getWicketSession().setLocale(getLocale());
 tester.getApplication().addComponentInstantiationListener(
 new SpringComponentInjector(tester.getApplication(),
 applicationContext));
 enhancedTester = new EnhancedWicketTester(tester);
 initSessionBeforeTest((UserSession) tester.getWicketSession());
}

First WicketTester object is created with Wicket Application object as constructor’s parameter. Note that Wicket Application object is taken from Spring’s ApplicationContext. Then Spring pre-configuration takes place and at the end Enhanced WicketTester is created.

Note also that two hook methods are called: getLocale and initSessionBeforeTest.

/**
 * Override to change locale
 * @return locale, default EN
 */
 protected Locale getLocale() {
 return new Locale("EN");
 }

Method getLocale returns default local for the tests. By default it returns EN, but extending classes can override this method to provide different locale.

 /**
 * Insert application specific properties to session
 * @param session
 */
 protected void initSessionBeforeTest(UserSession session) {
 // override in test if necessary
 }

Method initSessionBeforeTest is empty by default. It should be overridden if you would like to insert any test specific data into session before each test.

At the end helper classes are initialized.

private void initHelpers() {
 clicker = new Clicker(tester, enhancedTester);
 formFiller = new FormFiller(tester, enhancedTester);
 enterer = new Enterer(tester, enhancedTester, clicker, formFiller);
}

And that is it. Below WicketTestBase in its full glory:

public class WicketTestBase {

 @Autowired
 private ApplicationContext applicationContext;

 protected WicketTester tester;
 protected EnhancedWicketTester enhancedTester;
 protected Clicker clicker;
 protected Enterer enterer;
 protected FormFiller formFiller;

 public void init() {
     populateData();
     createTester();
     initHelpers();
 }

 private void createTester() {
     tester = new WicketTester((WebApplication)
                        applicationContext.getBean("wicketApplication"));
     tester.setupRequestAndResponse();
     tester.getWicketSession().setLocale(getLocale());
     tester.getApplication().addComponentInstantiationListener(
                      new SpringComponentInjector(tester.getApplication(),
                      applicationContext));
     enhancedTester = new EnhancedWicketTester(tester);
      initSessionBeforeTest((UserSession) tester.getWicketSession());
 }

 private void initHelpers() {
    clicker = new Clicker(tester, enhancedTester);
    formFiller = new FormFiller(tester, enhancedTester);
    enterer = new Enterer(tester, enhancedTester, clicker, formFiller);
 }

 /**
  * Override to change locale
  * @return locale, default EN
  */
 protected Locale getLocale() {
     return new Locale("EN");
 }

 /**
  * Insert application specific properties to session
  * @param session
  */
  protected void initSessionBeforeTest(UserSession session) {
     // override in test if necessary
  }

 /**
  * Override to populate data in database
  * for each test
  */
 protected void populateData() {
     // override in test if necessary
 }
}

Simplest example of test extending from WicketTestBase will look like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:testApplicationContext.xml"})
@Transactional
public class NameOfTheTest extends WicketTestBase {

    @Before
    public void init() {
        super.init();
    }

}

ContextConfiguration points to Spring’s configuration xml file (in this case testApplicationContext.xml) and Transactional annotation simply makes all test methods transactional. Worth mentioning is the fact that all this transactions are rolled back after each test method finish it’s execution, thus you won’t have to implement any destroyData method – this is automatically done for you.

Usage of WicketTestBase can be also found in WicketCool project. If interested, check it out.

see also:

  1. Writing readable and maintable integration tests (not only) in Wicket
  2. Test template you should always use
Advertisements
Categories: Wicket Tags: ,
  1. August 27, 2009 at 8:38 am

    Hi,

    First of all, congratulations for your blog !

    I’m a newbie on WicketTester, and I’d like to test a simple project using spring configured with annotations.

    I’ve set up a simple TestCase with wicket tester but my applicationContext remains “null”.

    Here’s an extract of my code :

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={“/springConfiguration.xml”})
    public class TestHomePage extends TestCase
    {
    private WicketTester tester;
    @Autowired
    private ApplicationContext appContext;
    public void setUp()
    {
    tester = new WicketTester((WebApplication) appContext.getBean(“wicketApplication”));
    }

    Do you have any idea about what is missing ?

    Thanks a lot for your help and hope to read other good articles from you soon !

    • paulszulc
      August 27, 2009 at 9:00 am

      I fear that the problem is that you are mnixing JUnit 3.x with 4.x. As I understand you dont get any exceptions from Spring, thus it means that it not even tries to inject the application context.
      Try to change your test so it looks like this:

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations={”/springConfiguration.xml”})
      public class TestHomePage // no extends
      {
      private WicketTester tester;
      @Autowired
      private ApplicationContext appContext;

      @Before // 4.x annotation
      public void setUp()
      {
      tester = new WicketTester((WebApplication) appContext.getBean(”wicketApplication”));
      }

      and tell me if it works.

      • August 27, 2009 at 9:13 am

        Ok this seems to do the trick.

        Thanks a lot I wasn’t seeking on the Junit side but on the Spring one.
        (unfortunately still got errors… i’ll investigate further).

        thanks again !

  2. Erik
    June 28, 2010 at 1:35 pm

    Hello. I have been trying to implement this with my application. My test applicationContext is basically a copy of my ordinary but with a different dataSource, referenced by the test page:
    @ContextConfiguration(locations = {“classpath:test/ApplicationContext.xml”})
    I get the applicationContext, a GenericApplicationContext with all my beans, but on creation of WicketTester – tester = new WicketTester((WebApplication) applicationContext.getBean(“wicketApplication”)); – I get “IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?”.
    WicketTester is not started via web.xml so that’s natural. Isn’t the GenericApplicationContext the context in the WebApplication here?
    I’m sorry if it’s obvious, I’m new to Spring and WicketTester.
    Thanks.

  1. August 25, 2009 at 8:51 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: