3.3 Testing Highlights

Testing is one of the most important aspects of software development. Without testing it would be difficult to determine if a piece of code worked properly, changes would have undetected consequences, and the quality of the code would generally be lower.

There are two major categories of testing generally recognised today: unit testing and integration testing. In the context of the GreenPages application, unit testing means testing a single class in isolation from other application code. This type of testing does not change at all when developing for Virgo and so the GreenPages sample does not include any unit tests.

In our application integration testing means testing an application or portion of an application with other code. This kind of testing does look a bit different when developing for Virgo. In most cases Virgo applications are made up of small bundles that consume services through the OSGi registry. The following highlights show how a single bundle and the entire GreenPages application can be integration tested outside the OSGi container.

Single Bundle Integration Test

One of the most common forms of integration testing is ensuring that the object relational mapping in an application is working properly. This kind of testing typically uses a data access object to retrieve data from a live database.

The greenpages.jpa.JpaDirectorySpringContextTests class in the src/test/java source folder of the greenpages.jpa project is such a test case for the JpaDirectory class. The class uses JUnit to run the test and tests that a directory search completes correctly. Rather than instantiate this class directly in the test, the Spring Test Framework is used to instantiate and inject a JpaDirectory bean defined in the META-INF/spring/module-context.xml file. Spring Test Framework declarations are used to run the test with the SpringJunit4ClassRunner and configure the test with the files classpath:/META-INF/spring/module-context.xml and classpath:/META-INF/spring/test-context.xml:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/META-INF/spring/module-context.xml",
    "classpath:/META-INF/spring/test-context.xml" })
@TestExecutionListeners(value = DependencyInjectionTestExecutionListener.class)
public class JpaDirectorySpringContextTests {

    @Autowired
    private Directory directory;

    @Test
    public void search() {

The test-context.xml file in the src/test/resources/META-INF/spring folder defines two beans: a DataSource and a TestDataPopulator:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      p:driverClassName="org.h2.Driver" p:url="jdbc:h2:.~/greenpages-db/greenpages"
      p:username="greenpages" p:password="pass" init-method="createDataSource"
      destroy-method="close" />

<bean class="greenpages.jpa.TestDataPopulator" init-method="populate">
      <constructor-arg ref="dataSource" />
      <constructor-arg value="file:../../db/db.sql" />
</bean>

These two beans provide a test DataSource complete with test data.

Multi Bundle Integration Test

The single bundle integration test provides a test implementation of its DataSource dependency. When integration testing, it is often a good idea to test the entire application outside of the container. GreenPages includes such a test case for the entire application, starting with the GreenPagesController class and descending all the way to a database. Although it would be sensible for this test case to reside in a separate test bundle, one of the bundles involved is a web bundle and so it is more convenient to locate the test case in the greenpages.web project.

Since this test case will be testing the GreenPages application as a whole, it needs to depend on the bundles that make up the application. The pom.xml file for the greenpages.web project contains a dependency declaration for the greenpages.jpa bundle:

<dependency>
      <groupId>com.springsource.dmserver</groupId>
      <artifactId>greenpages.jpa</artifactId>
      <version>${project.version}</version>
      <scope>test</scope>
</dependency>

Note that the scope of the dependency is test.

The GreenPagesSpringContextTests class in the src/test/java/greenpages/web folder contains Spring Test Framework declarations to run the test with the SpringJunit4ClassRunner and configure the test with the files classpath*:/META-INF/spring/module-context.xml, file:src/main/webapp/WEB-INF/greenpages-servlet.xml, and classpath:/META-INF/spring/test-context.xml. Note the use of classpath*: which causes Spring to look for files that match the specified path in all of the bundles on the classpath.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath*:/META-INF/spring/module-context.xml",
        "file:src/main/webapp/WEB-INF/greenpages-servlet.xml",
        "classpath:/META-INF/spring/test-context.xml" })
@TestExecutionListeners(value = DependencyInjectionTestExecutionListener.class)
public class GreenPagesSpringContextTests {