EQUIP2 WebApp Unit Testing

Chris Greenhalgh, 2007-02-06

Introduction

It is (apparently) a *good thing* to develop your application together with Unit tests. These allow you to:

Spring's dependency injection approach makes it relatively easy to test objects and parts of the system without having to run/test the whole web application.

This tutorial includes basic support for unit tests using JUnit. There are also specific examples of testing code which makes use of EQUIP2.

Defining and running tests

Running tests

The unit testing here is based on JUnit; refer to EQUIP2_WebApp_Configuring_and_Building for which version of Junit to get (4) and where to put it (in lib/junit-4.jar)

The tutorial build.xml has a target 'test' which:
> ant test

Adding a new test

To create a new test make a new java source file in the test/ directory hierarchy (traditionally the package is the same as the class(es) being tested, and the name is 'meaningful').

You will need to import org.junit.Test and import static org.junit.Assert.*. Each test should be a public method, which you should tag with the (java 1.5) attribute org.junit.Test ('@Test'). The test method should create any required data, run the test, and check for the correct results using the org.junit.Assert.* static methods, e.g. 'assertTrue(boolean)', which requires the argument to be true to mark success.

If the correct outcome is to throw an exception then tag the method with the expected exception class as a parameter of the Test tag, e.g. '@Test(expected= IndexOutOfBoundsException.class)'. See the JUnit documentation (e.g. cookbook and Javadocs) for more details.

Add the name of your new test class to the argument list of the org.junit.runner.JUnitCore java command in the build.xml file.

Now run the test(s) again.

Creating Testing

Testing controllers

See the Spring documentation (e.g. the web MVC tutorial and the reference documentation (e.g. chapter 23)) for more suggestions on unit testing controllers, etc. Spring also has some 'mock' objects whic implement the HttpServletRequest/Response APIs for testing controllers - see the Spring package org.springframework.mock.web.

See also the combined example, below.

The general idea is:

Testing with a dataspace

EQUIP2 has a number of different dataspace implementation. The web application normally uses the persistent version based on Hibernate over a RDBMS. However, for testing, other implementation can be used (avoiding the need to have a real database with suitable test data in it).

The tests directory in this tutorial includes a drop-in replacement for the normal IDAllocator class, equip2.spring.db.IDAllocator. This replacement will work with a transient (testing) dataspace, whereas the normal version depends on Hibernate and an underlying JDBC connection. There is a unit test for this replacement allocator: equip2.webapptutorial.testing.TestIDAllocator.

Some useful utility functions are collected into equip2.webapptutorial.testing.TestingUtils, in particular newTransientDataspace(), which creates a transient dataspace (!) and readXmlDump(IDataspace,File), which reads the objects from an EQUIP2 XML dump into the dataspace.

The test equip2.webapptutorial.testing.TestSimpleDataspaceExample includes an example of setting up a transient dataspace and testing some simple dataspace operations.

Warning

Note that there are a small number of differences between transient and hibernate dataspaces (and, of course, the implementations might have different bugs):

Combined testing example

The test equip2.webapptutorial.testing.TestRegisterPlayer demonstrates a number of useful testing elements:

Note that it is often possible to test controllers without a full HTTP mock request, e.g. using a pre-populated command or form-backing object.

If core game functionality is separated into distinct objects then it may not be worthwhile recreating the full application/servlet context, but rather the objects may be created and initialised directly.

Changes

2007-02-06