/ INTEGRATION TESTING, SPRING, SPRING MVC

Spring 3.2 sweetness

Even the most extreme Spring opponents have to admit it is all about making developers life easier. Version 3.2 of Spring MVC brings even more sweetness to the table.

Sweetness #1: No web.xml

The ability to run a webapp without any web deployment descriptor comes from Servlet 3.0.

One option would be to annotate your servlet with the @WebServlet annotation to set mapping and complementary data. When you get your servlet for free, like Spring’s DispatcherServlet, you’d need to subclass you servlet for no other purpose than adding annotation(s).

Alternatively, Servlet 3.0 offers a way to both programmatically register servlets in the container and to offer hooks at startup through the ServletContainerInitializer interface. The container will call the onStartup() method of all concrete implementation at webapp startup. The Spring framework leverages this feature to do so for WebApplicationInitializer instances.

Spring MVC 3.2 provides such an implementation - AbstractContextLoaderInitializer, to programmatically register the DispatcherServlet. This means that as soon as the spring-webmvc jar is in the WEB-INF/lib folder of the webapp, you’ve got the Dispatcher servlet up and ready.

This replaces both the servlet and servlet mapping and the context listener declarations in the web.xml.

Sweetness #2: Easy Java configuration integration

Java configuration is the way to configure Spring injection explicitly in a typesafe way. I won’t go into the full demonstration of it, as I already wrote about that some time ago.

Earlier Spring versions provided a way to use Java configuration classes instead of XML files in the web deployment descriptor. Spring 3.2 offers AbstractAnnotationConfigDispatcherServletInitializer, a AbstractContextLoaderInitializer subclass with hooks for Java configuration classes.

Your own concrete subclass has to implement methods to define servlet mappings, as well as root and web Java configuration classes:

public class SugarSpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { JavaConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

At this point, you just need to create those configuration classes.

Sweetness #3: integration testing at the mapping level

Your code should be unit-tested, that is tested in isolation to ensure that each method is bug-free, and integration-tested to ensure that collaboration between classes yield expected results.

Before v. 3.2, the Spring test framework let you assemble your configuration classes / files easily enough. The problem lay in the way you would call entry-points - the controllers. You could call methods of those controllers, but not the mappings, leaving those untested.

With v. 3.2, Spring Test brings a whole MVC testing framework which entry-points are mappings. This way, instead of testing method x() of controller C, you would test a request to /z, letting Spring MVC handle it so we can check for expected results.

The framework also provide expectations for view returning, forwarding, redirecting, and model attribute setting, all with the help of a specific DSL:

public class SayHelloControllerIT extends AbstractTestNGSpringContextTests {

    private MockMvc mockMvc;

    @BeforeMethod
    public void setUp() {
        mockMvc = webAppContextSetup((WebApplicationContext) applicationContext).build();
    }

    @Test(dataProvider = "pathParameterAndExpectedModelValue")
    public void accessingSayhelloWithSubpathShouldForwardToJspWithModelFilled(String path, String value) throws Exception {
        mockMvc.perform(get("/sayHello/Jo")).andExpect(view().name("sayHello")).andExpect(model().attribute("name", "Jo"));
    }
}

The project for this article can be downloaded in Eclipse/Maven format.

To go further:

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Spring 3.2 sweetness
Share this