Spring-test-mvc is now packaged with Spring-test module as of Spring 3.2RC1 and has made a few changes which is what I wanted to record for myself here:
First is to include the Spring-test-mvc module, the following is the dependency now that it is packaged with spring-test module:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.2.0.RC1</version> <scope>test</scope> </dependency>
Now on the test side the first change is to include a @WebAppConfiguration annotation:
@WebAppConfiguration @ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/mvc-config.xml", "classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-jpa.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public class MemberJsonControllerTest { @Autowired private WebApplicationContext wac;
This new annotation instructs Spring test support to load up a WebApplicationContext - a mock ServletContext is automatically assigned to this WebApplicationContext.
Another change from previous version of Spring-test-mvc is the updated package names, the following are the new static imports:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
Now that a WebApplicationContext is available in the scope of the test, the next step is to get hold of MockMvc which will drive all the controller related tests:
private MockMvc mockMvc; @Before public void setup() { this.mockMvc = webAppContextSetup(this.wac).build(); }
Once a MockMvc instance is available all the controller tests can be driven using this, consider the following test where I have a series of CRUD actions and tests on the results being performed on a controller:
@Test public void testAControllerFlow() throws Exception { this.mockMvc.perform(post("/membersjson").contentType(MediaType.APPLICATION_JSON).content(String.format(createJson, 1,"One","One", 0).getBytes())) .andExpect(status().isOk()); this.mockMvc.perform(post("/membersjson").contentType(MediaType.APPLICATION_JSON).content(String.format(createJson, 2,"Two","Two", 0).getBytes())) .andExpect(status().isOk()); this.mockMvc.perform(post("/membersjson").contentType(MediaType.APPLICATION_JSON).content(String.format(createJson, 3,"Three","Three", 0).getBytes())) .andExpect(status().isOk()); this.mockMvc.perform(get("/membersjson").contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string(containsString(membersJson))); this.mockMvc.perform(put("/membersjson").contentType(MediaType.APPLICATION_JSON).content(String.format(createJson, 1,"One","OneUpdated", 0).getBytes())) .andExpect(status().isOk()); mockMvc.perform(get("/membersjson").contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$[0].first").value("One")); mockMvc.perform(get("/membersjson/1").contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string(containsString("OneUpdated"))); }
The tests are very readable thanks to the fluent interfaces and supports matchers on response data based on Hamcrest which I have used above(containsString) and also supports jsonpath for validating json responses.
I have a github project which provides the complete working sample: https://github.com/bijukunjummen/spring-mvc-test-sample.git