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