
Testing Support
• An important tenant of the Spring Framework has always been the development of application code
that is easy to test (unit and integration).
• To this end, a new Spring TestContext Framework was added in Spring 2.5 to better facilitate unit
testing.
• Prior to Spring 2.5, Spring provided unit/integration testing support through JUnit.
• The new Spring framework allows application testing to be agnostic; independent of any actual testing
framework.
• This allows JUnit 3.x, JUnit 4.x, TestNG or other unit testing framework to be used under the covers.
• However, the new Spring testing framework does require Java 5.
• The Spring project team recommends using the new Spring TestContext Framework for all new
applications (over JUnit for older applications).
• As with almost everything in Spring 2.5, unit testing in the new TestContext Framework is driven by
annotation.
• To demonstrate the TestContext Framework, examine the two simple Spring Beans.
package com.intertech;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
public class Stuff {
private Thing thing;
public Thing getThing() {
return thing;
}
@Autowired
public void setThing(Thing thing) {
this.thing = thing;
}
}
package com.intertech;
public class Thing {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
• To create a “main” or driver unit testing class, simply create a Java class and annotate the class with the
following TestContext annotations.
Package com.intertech;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
public class StuffTest extends AbstractJUnit38SpringContextTests{
@Autowired
private Stuff s;
}
• The first annotation is a JUnit 4 convenience annotation that allows any class to serve as the unit test
“runner” without extending any other class.
• Without this annotation, the test class would have to extend one of the unit testing framework abstract
classes.
• In JUnit 3.8 for example, StuffTest would extend org.springframework.test.context.junit38.
AbstractJUnit38SpringContextTests
• The @ContextConfiguration annotation indicates the location of configuration information files for the
test class.
• The locations attribute is an array containing the resource locations of XML bean configuration files.
• Typically, the location attribute is set to the same set of bean config files as used in web.xml or other
deployment configuration file.
• The location attribute is optional.
...
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class StuffTest extends AbstractJUnit38SpringContextTests{
...
• If left off, then in this example the configuration information would have to be in a file called “StuffTest-
context.xml” in the com.intertech package.
• When using the JUnit 4 @RunWith annotation, any method in the test class becomes a test method by
simply annotating it with @Test.
• The code below provides two simple unit test methods for the Stuff class above.
@Test
public void useStuff() {
assertNotNull(s.getThing().getName());
}
@Test
public void checkName(){
assertEquals(s.getThing().getName(), "Jim");
}
• When not using JUnit 4 and @RunWith, the methods may have to adhere to certain naming conventions.
• For example, when using JUnit 3.8 the method names would need to begin with “test” (when extending
AbstractJUnit38SpringContextTests).
• A common set of TestContext framework annotations can be used with any underlying test framework
• For example, to time a method to ensure it executes in a set amount of time, use the @Timed annotation
with a specified milliseconds attribute.
@Test
@Timed(millis=1000)
public void useStuff() {
assertNotNull(s.getThing().getName());
}
• The list of testing annotations are provided in the table below.
Common Testing Annotations
@IfProfileValue
@ ProfileValueSourceConfiguration
@ExpectedException
@Timed
@Repeat
• When using JUnit 4, other methods such as before test and after test methods can be defined with JUnit
4 specific annotations as well.
@Before
public void start() {
System.out.println("starting my test");
}
@After
public void ending() {
System.out.println("ending tests");
}
• A common issue when performing unit tests with a real database is that the testing often modifies the
data and therefore affects future tests.
• Furthermore, many data changing operations cannot be verified outside of a transaction.
• For example, a transaction must exist to check the database for a newly inserted row.
• In Spring 2.5, the testing framework transactions create and then roll back a transaction for each test.
• Test code is written that just assumes the existence of a transaction for each test. But the data is
preserved for future tests.
• If a transaction should need to commit during a test, the framework can be instructed to have the
transaction commit instead of rollback.
• A set of transaction annotations are provided to configure and manage the transactions in the unit test.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
public class FictitiousTransactionalTest {
@BeforeTransaction
public void verifyInitialDatabaseState() {
// logic to verify the initial state before a transaction is started
}
@Before
public void setUpTestDataWithinTransaction() {
// set up test data within the transaction
}
@Test
// overrides the class-level defaultRollback setting
@Rollback(true)
public void modifyDatabaseWithinTransaction() {
// logic which uses the test data and modifies database state
}
@After
public void tearDownWithinTransaction() {
// execute "tear down" logic within the transaction
}
@AfterTransaction
public void verifyFinalDatabaseState() {
// logic to verify the final state after transaction has rolled back
}
@Test
@NotTransactional
public void performNonDatabaseRelatedAction() {
// logic which does not modify database state
}
}
Testing Support
Table of Contents
online learning aid. Any attempts to copy, reproduce, or use for training is strictly prohibited.
Courseware
Training Resources
Tutorials