Thursday, 6 September 2012

Spring MVC Controller JUnit Testing

JUnit testing Spring MVC controllers is not an easy task. But recently, a new project (now included in Spring 3.2) offers new tools to facilitate this. This post illustrates how to test a simple controller via JUnit tests.

This code is a variation of the code used in JUnit Testing Spring Service and DAO (with In-Memory Database). It is available from Gihut in the Spring-MVC-JUnit-Testing directory.

Test Configuration Classes

These are identical to those required for Service and DAO testing.

Controller

Our controller:
@Controller
public class MyController {

    @Autowired
    private MyService myService;

    @RequestMapping(value = "/")
    public String home(Model model) {

        return "index";

    }

    @RequestMapping(value = "/roundtrip")
    public String persistenceStatus(Model model) {

        MilliTimeItem retr = myService.createAndRetrieve();
        model.addAttribute("RoundTrip", retr);

        return "roundtrip";

    }

}

Controller Testing

The following creates an instance of MockMvc to test simulated user requests:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ JpaTestConfig.class, TestConfig.class })
public class MyControllerTest {

    private MockMvc mockMvc;

    @Before
    public void setup() {

        mockMvc = MockMvcBuilders
            .annotationConfigSetup(JpaTestConfig.class, TestConfig.class)
            .build();

    }

    @Test
    public void testHome() throws Exception {

        mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(forwardedUrl("WEB-INF/pages/index.jsp"));

    }

    @Test
    public void testPersistenceStatus() throws Exception {

        mockMvc.perform(get("/roundtrip"))
            .andExpect(status().isOk())
            .andExpect(forwardedUrl("WEB-INF/pages/roundtrip.jsp"))
            .andExpect(model().attributeExists("RoundTrip"));

    }

}
The / request verifies the returned status and the URL mapping to the JSP page. The /roundtrip request makes sure the returned model does contain the Roundtrip attribute.

Dependencies

The Spring MVC test artifact is not yet available from maven's central repository. It should be obtained from another repository:
<repositories>
    <repository>
        <id>spring.test-mvc</id>
        <url>http://repo.springsource.org/libs-milestone</url>
    </repository>
</repositories>
The required dependency are:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test-mvc</artifactId>
    <version>1.0.0.M1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

More Spring related posts here.

4 comments:

  1. Hello great tutorial, but from where did you get methods (get(), status(), forwardedUrl())in perform method.

    ReplyDelete
    Replies
    1. From static imports (see the code):

      import static org.springframework.test.web.server.request.MockMvcRequestBuilders.get;
      import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;

      Delete
  2. Hi... great post about mockmvc

    If you have time, can you post an updated example for Spring 3.2.2 testing GET and POST/PUT requests, and using andExpect(model()... ?

    ReplyDelete