Подтвердить что ты не робот

Тестирование Spring @RequestBody с использованием Spring MockMVC

Я пытаюсь проверить метод, который отправляет объект в базу данных с помощью Spring MockMVC framework. Я построил тест следующим образом:

@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();
}

Метод, который я тестирую, использует Spring @RequestBody для получения ObjectBean, но тест всегда возвращает ошибку 400.

@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;
}

json, созданный gson в тесте:

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

Класс ObjectBean

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
}

Итак, мой вопрос: как проверить этот метод с помощью Spring MockMVC?

4b9b3361

Ответ 1

Используйте этот

public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));

@Test
public void testInsertObject() throws Exception { 
    String url = BASE_URL + "/object";
    ObjectBean anObject = new ObjectBean();
    anObject.setObjectId("33");
    anObject.setUserId("4268321");
    //... more
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
    ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
    String requestJson=ow.writeValueAsString(anObject );

    mockMvc.perform(post(url).contentType(APPLICATION_JSON_UTF8)
        .content(requestJson))
        .andExpect(status().isOk());
}

Как описано в комментариях, это работает, потому что объект преобразуется в json и передается как тело запроса. Кроме того, contentType определяется как Json (APPLICATION_JSON_UTF8).

Дополнительная информация о структуре тела HTTP-запроса

Ответ 2

Проблема заключается в том, что вы сериализуете свой bean с помощью настраиваемого объекта Gson, в то время как приложение пытается десериализовать ваш JSON с помощью Jackson ObjectMapper (внутри MappingJackson2HttpMessageConverter).

Если вы откроете журналы своего сервера, вы увидите что-то вроде

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.Date from String value '2013-34-10-10:34:31': not a valid representation (error: Failed to parse Date value '2013-34-10-10:34:31': Can not parse date "2013-34-10-10:34:31": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
 at [Source: [email protected]; line: 1, column: 20] (through reference chain: com.spring.Bean["publicationDate"])

среди других трасс стека.

Одним из решений является установка формата даты Gson для одного из указанных выше (в стеке).

Альтернативой является регистрация вашего собственного MappingJackson2HttpMessageConverter путем настройки вашего собственного ObjectMapper на тот же формат даты, что и ваш Gson.

Ответ 3

следующие работы для меня,

  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);
    }
}