Pivotal Knowledge Base

Follow

Spring Framework: How To Migrate Spring Unit Tests from JUnit 3 to JUnit 4

Environment

 Product  Version
 Spring Framework  2.5/3.0/3.1

Purpose

Previously, when writing unit tests with the Spring Framework and JUnit3, users would extend one of the Spring Framework's abstract JUnit test classes. In recent versions of Spring Framework and with JUnit 4, users are encouraged to make use of annotations in test classes. This article provides information on converting a JUnit 3 test case based on Spring's abstract JUnit test classes to a JUnit 4 test case based on annotations.

Resolution

This section provides information on how JUnit 3 has changed with JUnit 4, as well as how Spring's test support has changed from JUnit 3 to JUnit 4.

Changes from JUnit 3 to JUnit 4

The main difference from JUnit 3 to JUnit 4 is that JUnit 3 is based on class inheritance, whereas JUnit 4 is based on annotations. This means that with JUnit 3 test cases will extend TestCase, whereas JUnit 4 classes do not have to extend anything. With JUnit 4, a class will be considered a unit test when it contains one or more test cases. This leads to the second major difference. With JUnit 3, test cases are found by analyzing method signatures. Each test must have a name that begins with the test, has no parameters and returns void. With JUnit 4, test cases are located by looking for the method level annotation @Test.

Finally, as a result of the change from an inheritance based framework to an annotations based framework, the assert* methods and the fixtures (i.e. setup, tearDown, etc...) are no longer available as class methods on a unit test. Instead, the assert* methods can be imported from the org.junit.Assert class and the fixtures are specified with additional annotations like @Before and @After.

The following example outlines the changes mentioned above. For more information on using either JUnit 3 or JUnit 4, see the project documentation.

Example:

JUnit 3

import junit.framework.TestCase;
public class MyTest extends TestCase {
@Override
protected void setUp() {
...
}
public void testIWillFail() {
     assertEquals(1, 2);
}
}

JUnit 4

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
public class MyTest {
@Before
public void setUp() {
   ...  // Note, method name can be anything
}
@Test
public void iWillAlwaysFail() {
     // available through "import static"
        //   on Assert
     assertEquals(1, 2);
  }
}

Changes in Spring Test Support

To support the changes in JUnit 4, the Spring Framework's testing support was redesigned. Keeping with the theme of JUnit 4, annotations were used to enable the features which make integration testing on the Spring Framework much easier. 

As with the change from JUnit 3 to JUnit 4, test cases that were previously extending a class, like AbstractJUnit38SpringContextTests, no longer need to do so. Instead, simply annotate the class with @RunWith(SpringJUnit4ClassRunner.class) and @ContextConfiguration. The first @RunWith annotation enables Spring to assert additional control over the given test cases. When used in conjunction with @ContextConfiguration, this allows the unit test to load an application context, perform dependency injection and access other functionality available through the Spring Framework.

Example:

import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration
public class MyTest { @Test    public void doSomething() {   ...   } }

Note@ContextConfiguration, by default, looks for a Spring bean definition file located at classpath:com/example/MyTest-context.xml. This is a convention used by the Spring Framework to minimize the amount of configuration required. If you would like to specify an explicit path to a Spring bean definition file, pass an array of Strings to the locations argument of the @ContextConfiguration annotation. The specified bean definition files are then loaded and available for use by a test case. For more information, see the Spring Framework 3.0 manual.

As of Spring Framework 3.1.0, it is also possible to specify annotated classes which contain Spring bean definitions. This is done by passing one or more annotated classes to the classes argument of the @ContextConfiguration annotation.
 
Note: Only the classes or the locations argument can be specified, not both. For more information, see the Spring Framework 3.1manual.

Comments

Powered by Zendesk