I’ve recently switched from using JUnit 3.x to JUnit 4 for most new unit tests I write. One area that causes trouble is the use of JUnit 3.x based test base classes. Spring has a tree of helper classes based on junit.framework.TestCase
that make writing tests that use an ApplicationContext, dependency injection or transactions easier. These base classes can autowire your test so that your member variables are initialized and ready to go, pointing to beans managed by Spring.
I wanted the functionality provided by these base classes but wanted to continue to write tests in the JUnit4 style. The two best features of JUnit 4 are the @BeforeClass/@AfterClass
annotations and the ability to have multiple setUp and tearDown methods using @Before
and @After
. Switching back to JUnit 3 just to use the base class seemed unfortunate.
My first attempt was to extend my JUnit 4 test from Spring’s class, AbstractDependencyInjectionSpringContextTests
. When JUnit runs, it inspects your class through reflection and decides if it’s a JUnit 3 or 4 class. It sees that since Spring’s class derives from junit.framework.TestCase and so runs it as a JUnit 3 test using org.junit.internal.runners.OldTestClassRunner
.
You can circumvent JUnit’s decision about this test and force it to be run as a JUnit 4 test instead using the annotation RunWith((TestClassRunner.class)
. This forces JUnit to use the new test runner (TestClassRunner) even though the class derives from TestCase
. I created a class called SpringManagedTests
that derives from AbstractDependencyInjectionSpringContextTests
and is annotated with RunWith
. (My tests will extend SpringManagedTests
).
Next, JUnit 4 only cares about annotations and won’t run the old setUp and tearDown methods defined by the Spring classes. To get around this, add methods with Before
and After
annotations to call setUp and tearDown.
@Before final public void callSetup () throws Exception { super . setUp (); } @After public void callTearDown () throws Exception { super . tearDown (); }
All features of the base class are now available, and JUnit 4 annotated test methods run as you would expect. The final test base class is below. To use it, derive your test from SpringManagedTests
and read the docs on AbstractDependencyInjectionSpringContextTests
for information on having Spring wire members of your class. In my case I use field injection – I have member variables declared as protected with the field name matching the bean name. When the test runs the field are populated.
This technique could be used for other JUnit 3 based test frameworks as well. It’s not as clean as having a pure JUnit 4 implementation but works well until that happens.
import org. junit. After; import org. junit. Before; import org. junit. internal. runners. TestClassRunner; import org. junit. runner. RunWith; import org. springframework. test. AbstractDependencyInjectionSpringContextTests; /** * A base class for tests that load a spring application context * and use dependency injection to populate fields in the test class. * Unlike AbstractDependencyInjectionSpringContextTests, this * class can be used as a base class for JUnit 4 tests. * @author dyoung */ // RunWith is required to force what would otherwise look like a JUnit 3.x test // to run with the JUnit 4 test runner. @RunWith ( TestClassRunner. class ) public class SpringManagedTests extends AbstractDependencyInjectionSpringContextTests { // pass through to the junit 3 calls, which are not annotated @Before final public void callSetup () throws Exception { super . setUp (); } @After public void callTearDown () throws Exception { super . tearDown (); } } From : http://dmy999.com/article/21/adapting-a-springs-junit-3x-base-classes-to-junit-4