Integration Testing POSTing an entire object to Spring MVC controller
I had the same question and it turned out the solution was fairly simple, by using JSON marshaller.
Having your controller just change the signature by changing @ModelAttribute("newObject")
to @RequestBody
. Like this:
@Controller@RequestMapping(value = "/somewhere/new")public class SomewhereController { @RequestMapping(method = RequestMethod.POST) public String post(@RequestBody NewObject newObject) { // ... }}
Then in your tests you can simply say:
NewObject newObjectInstance = new NewObject();// setting fields for the NewObject mockMvc.perform(MockMvcRequestBuilders.post(uri) .content(asJsonString(newObjectInstance)) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON));
Where the asJsonString
method is just:
public static String asJsonString(final Object obj) { try { final ObjectMapper mapper = new ObjectMapper(); final String jsonContent = mapper.writeValueAsString(obj); return jsonContent; } catch (Exception e) { throw new RuntimeException(e); }}
One of the main purposes of integration testing with MockMvc
is to verify that model objects are correclty populated with form data.
In order to do it you have to pass form data as they're passed from actual form (using .param()
). If you use some automatic conversion from NewObject
to from data, your test won't cover particular class of possible problems (modifications of NewObject
incompatible with actual form).
I believe that I have the simplest answer yet using Spring Boot 1.4, included imports for the test class.:
public class SomeClass { /// this goes in it's own file//// fields go here}import org.junit.Beforeimport org.junit.Testimport org.junit.runner.RunWithimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestimport org.springframework.http.MediaTypeimport org.springframework.test.context.junit4.SpringRunnerimport org.springframework.test.web.servlet.MockMvcimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.postimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status@RunWith(SpringRunner.class)@WebMvcTest(SomeController.class)public class ControllerTest { @Autowired private MockMvc mvc; @Autowired private ObjectMapper mapper; private SomeClass someClass; //this could be Autowired //, initialized in the test method //, or created in setup block @Before public void setup() { someClass = new SomeClass(); } @Test public void postTest() { String json = mapper.writeValueAsString(someClass); mvc.perform(post("/someControllerUrl") .contentType(MediaType.APPLICATION_JSON) .content(json) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); }}