From JUnit to SpringUnit Tests

SpringUnit Test

Previous
The final refactoring converts the CompositeDateConstructorTest from a JUnit test to a SpringUnit test. The complete source code is given here.
package org.springunit.examples.constructor.springunit.v1;

public class CompositeDateConstructorTest extends SpringUnitTest {
	
    public SpringUnitContext getCompositeDateConstructorTest() {
        return compositeDateConstructorTest;
    }

    public void setCompositeDateConstructorTest(
            SpringUnitContext compositeDateConstructorTest) {
        this.compositeDateConstructorTest = compositeDateConstructorTest;
    }

    public void testJan01() throws Exception {
        runConstructor();
    }
	
    public void testDec31() throws Exception {
        runConstructor();
    }
	
    public void testFeb29Leap2000() throws Exception {
        runConstructor();
    }
	
    public void testFeb29Leap2004() throws Exception {
        runConstructor();
    }
	
    public void testApr31() throws Exception {
        runConstructor();
    }
	
    public void testJun31() throws Exception {
        runConstructor();
    }
	
    public void testSep31() throws Exception {
        runConstructor();
    }
	
    public void testNov31() throws Exception {
        runConstructor();
    }
	
    public void testFeb31() throws Exception {
        runConstructor();
    }
	
    public void testFeb30() throws Exception {
        runConstructor();
    }
	
    public void testFeb29NoLeap() throws Exception {
        runConstructor();
    }
	
    public void testFeb29NoLeap1900() throws Exception {
        runConstructor();
    }
	
    protected void runConstructor() throws Exception {
        Integer day = getObject("day");
        Integer month = getObject("month");
        Integer year = getObject("year");
        Integer expectedDay = getObject("expectedDay");
        Integer expectedMonth = getObject("expectedMonth");
        Integer expectedYear = getObject("expectedYear");
        Exception expectedException = getObject("expectedException");
        try {
            CompositeDate subject = new CompositeDate(year, month, day);
            if (expectedException != null) {
                fail("Exception not thrown");
            }
            assertTrue(expectedMonth == subject.getMonth());
            assertTrue(expectedDay == subject.getDay());
            assertTrue(expectedYear == subject.getYear());
        }
        catch (Exception ex) {
            if (!expectedException.getClass().isAssignableFrom(ex.getClass())) {
                throw ex;
            }
        }
    }

    private SpringUnitContext compositeDateConstructorTest;

}
If we compare this with the last version of the JUnit test Unifying the Test Algorithm, we notice that the code for the tests and runConstructor is unchanged. The SpringUnit test is now a JavaBean having the property CompositeDateConstructorTest, of type org.springunit.framework.SpringUnitContext. This property replaces the data map, which itself is now a property of SpringUnitContext objects. Turning the test into a bean is a crucial step; because of that, it can now be configured using Spring's dependency injection mechanism. An excerpt from the corresponding configuration file (named CompositeDateConstructorTest.xml) is shown next. The correspondence between the initialization of the data map in the JUnit code and its representation in XML should be obvious.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="compositeDateConstructorTest" class="org.springunit.framework.SpringUnitContext">
        <property name="data">
            <map>
                <entry key="testJan01">
                    <map>
                        <entry key="year">
                            <value type="java.lang.Integer">2006</value>
                        </entry>
                        <entry key="month">
                            <value type="java.lang.Integer">1</value>
                        </entry>
                        <entry key="day">
                            <value type="java.lang.Integer">1</value>
                        </entry>
                        <entry key="expectedYear">
                            <value type="java.lang.Integer">2006</value>
                        </entry>
                        <entry key="expectedMonth">
                            <value type="java.lang.Integer">1</value>
                        </entry>
                        <entry key="expectedDay">
                            <value type="java.lang.Integer">1</value>
                        </entry>
                    </map>
                </entry>
                <!-- More data elements defined here -->
                <entry key="testFeb29NoLeap">
                    <map>
                        <entry key="year">
                            <value type="java.lang.Integer">2003</value>
                        </entry>
                        <entry key="month">
                            <value type="java.lang.Integer">2</value>
                        </entry>
                        <entry key="day">
                            <value type="java.lang.Integer">29</value>
                        </entry>
                        <entry key="expectedException">
                            <bean class="org.springunit.examples.InvalidDateException"/>
                        </entry>
                    </map>
                </entry>
            </map>
        </property>
    </bean>
</beans>
It is worth enumerating the benefits of the conversion of the JUnit test to a Spring-configured Java Bean.
  • Data values have been removed from code into a configuration file, with the ancillary benefit that those values can be changed without recompiling code.
  • Using the Spring framework in particular means that the structure of the configuration file is one with which a large and still-growing body of developers is familiar.
  • Because org.springunit.framework.SpringUnitTest extends the org.springframwork.test.AbstractDependencyInjectionSpringContextTests class, the underlying map that holds all of the test data is in fact instantiated only once per execution.
By combining the JUnit and Spring frameworks, SpringUnit holds the potential for developers to produce unit tests that are easier to create and maintain than those coded from scratch.
Previous