I have a controller that writes to the ModelMap
like this:
@Controller
@RequestMapping("/dataset")
public class DatasetController {
@Autowired
DatasetDao datasetDao;
@RequestMapping(method = RequestMethod.GET)
public String getDataset(@RequestParam String name, ModelMap model) {
Dataset ds = datasetDao.get(name);
model.addAttribute("response", new DatasetResponse(ds));
return "Success";
}
I want to write a test case that gets a dataset and then performs more actions based on its contents. But, I'm having trouble getting data out of the service. My test case so far is:
@Test
public void testProducesXml() throws Exception {
mockMvc.perform(get("/dataset.xml").param("name", "foo"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(model().attribute("Response",
hasProperty("name", is("foo"))))
.andExpect(xpath("/dataset/name").string("foo"));
}
The model().attribute
line passes, but the test fails at xpath
with:
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
Ultimately I'd like to get a copy of the DatasetResponse
in my test function so I can do other things with it. I tried using andReturn()
, but that fails for the same reason that xpath
fails.
It turns out that even though there's a DatasetResponse
in the model, the body of the response is empty:
ModelAndView:
View name = Success
View = null
Attribute = Response
value = org.vpac.web.model.response.DatasetResponse@457fdd58
errors = []
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
However if I start the app in Tomcat and go to /dataset.xml?name=foo
in my browser, I can see the data as XML.
So, why is the body empty, and how can I get a reference to the DatasetResponse
? Edit Do I need to trigger the view to render the model, or something?
This came down to the test being misconfigured: my MVC config is split across two files, as specified in my
web.xml
file:But following examples from elsewhere, I only had my test class annotated with:
Adding the missing
mvc-dispatcher-servlet.xml
fixes the problem:Now the ModelAndView contain the objects that I return from the controller, and the body of the response is not empty.
.andExpect(xpath
works as expected, and I can get a copy of the response object with: