MVC Test Framework arrived with Spring 3.2. It allows to write integration tests (well... almost) for your Spring MVC @Controller(s)
One of server-side cornerstones is MockMvc class. It allows to execute requests on your Controllers very easily, but it needs to be initialized before it is used. Threre are two ways to initialize MockMvc and choice depends on how broad integration with other Spring MVC components your tests need. In my case, it was custom view resolver and few others I removed for sake of simplicity.
First is meant for simple single Controller testing
@Test public void foo() { TestedController controller = new TestedController(); MyCustomViewResolver resolver = new MyCustomViewResolver(); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).setViewResolvers(resolver).build(); MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/foo")).andReturn(); //parse and assert response.getContentAsString() as view was resolved by MyCustomViewResolver }You can employ extensive set of spring-mvc usual suspects, like ConversionService, ViewResolvers, MessageConverters, ... see StandaloneMockMvcBuilder javadoc
All this manual assembling makes me feel little unconfortable. Normaly all those beans are wired together in Spring Dispatcher context.
Another way to initlialize MockMvc is using @WebAppConfiguration and MockMvcBuilders.webAppContextSetup(webAppContext)
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = TestMvcSpringConfig.class) public class FooTests { @Autowired private WebApplicationContext webAppContext; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build(); } @Test public void foo() { MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/foo")).andReturn(); MockHttpServletResponse response = result.getResponse(); //parse and assert response.getContentAsString() as view was resolved by MyCustomViewResolver } @EnableWebMvc @Configuration public static class TestMvcSpringConfig extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Bean public TestedController getController() { return new TestedController(); } @Bean public ViewResolver viewResolver() { MyCustomViewResolver resolver = new MyViewCustomResolver(); return resolver; } }
For some unknown reason (that disappeared as quickly as it appeared) Spring was failing to create @EnableWebMvc annotated @Configuration, complaining about missing servlet context. I had to get my hands dirty and roll my own Spring web context. So for completeness, here is how it was done using MockServletContext. May be useful sometime.
@Test public void test() throws Exception { MockServletContext servletContext = new MockServletContext(); AnnotationConfigWebApplicationContext springContext = new AnnotationConfigWebApplicationContext(); springContext.setServletContext(servletContext); springContext.register(TestMvcSpringConfig.class); springContext.refresh(); MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(springContext).build(); MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/foo")).andReturn(); }
Happy Spring MVC testing!
No comments:
Post a Comment