Testing Spring's @RequestBody using Spring MockMVC

Viewed 198587

I am trying to test a method that posts an object to the database using Spring's MockMVC framework. I've constructed the test as follows:

@Test
public void testInsertObject() throws Exception { 

    String url = BASE_URL + "/object";

    ObjectBean anObject = new ObjectBean();
    anObject.setObjectId("33");
    anObject.setUserId("4268321");
    //... more

    Gson gson = new Gson();
    String json = gson.toJson(anObject);

    MvcResult result = this.mockMvc.perform(
            post(url)
            .contentType(MediaType.APPLICATION_JSON)
            .content(json))
            .andExpect(status().isOk())
            .andReturn();
}

The method I'm testing uses Spring's @RequestBody to receive the ObjectBean, but the test always returns a 400 error.

@ResponseBody
@RequestMapping(    consumes="application/json",
                    produces="application/json",
                    method=RequestMethod.POST,
                    value="/object")
public ObjectResponse insertObject(@RequestBody ObjectBean bean){

    this.photonetService.insertObject(bean);

    ObjectResponse response = new ObjectResponse();
    response.setObject(bean);

    return response;
}

The json created by gson in the test:

{
   "objectId":"33",
   "userId":"4268321",
   //... many more
}

The ObjectBean class

public class ObjectBean {

private String objectId;
private String userId;
//... many more

public String getObjectId() {
    return objectId;
}

public void setObjectId(String objectId) {
    this.objectId = objectId;
}

public String getUserId() {
    return userId;
}

public void setUserId(String userId) {
    this.userId = userId;
}
//... many more
}

So my question is: how to I test this method using Spring MockMVC?

4 Answers

the following works for me,

  mockMvc.perform(
            MockMvcRequestBuilders.post("/api/test/url")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(asJsonString(createItemForm)))
            .andExpect(status().isCreated());

  public static String asJsonString(final Object obj) {
    try {
        return new ObjectMapper().writeValueAsString(obj);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

I have encountered a similar problem with a more recent version of Spring. I tried to use a new ObjectMapper().writeValueAsString(...) but it would not work in my case.

I actually had a String in a JSON format, but I feel like it is literally transforming the toString() method of every field into JSON. In my case, a date LocalDate field would end up as:

"date":{"year":2021,"month":"JANUARY","monthValue":1,"dayOfMonth":1,"chronology":{"id":"ISO","calendarType":"iso8601"},"dayOfWeek":"FRIDAY","leapYear":false,"dayOfYear":1,"era":"CE"}

which is not the best date format to send in a request ...

In the end, the simplest solution in my case is to use the Spring ObjectMapper. Its behaviour is better since it uses Jackson to build your JSON with complex types.

@Autowired
private ObjectMapper objectMapper;

and I simply used it in my test:

mockMvc.perform(post("/api/")
                .content(objectMapper.writeValueAsString(...))
                .contentType(MediaType.APPLICATION_JSON)
);
Related