我正在尝试使用Spring的MockMVC框架测试将对象发布到数据库的方法。我构建了如下测试:
@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;
}
gson在测试中创建的json:
{
"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测试此方法?
答案 0 :(得分:45)
使用此
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)。
答案 1 :(得分:6)
以下对我有用的
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);
}
}
答案 2 :(得分:4)
问题是,当应用程序尝试使用Jackson Gson
(在ObjectMapper
内)反序列化您的JSON时,您正在使用自定义MappingJackson2HttpMessageConverter
对象序列化您的bean。
如果打开服务器日志,您应该会看到类似
的内容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: java.io.StringReader@baea1ed; line: 1, column: 20] (through reference chain: com.spring.Bean["publicationDate"])
其他堆栈跟踪。
一种解决方案是将Gson
日期格式设置为上述之一(在堆栈跟踪中)。
另一种方法是通过将自己的MappingJackson2HttpMessageConverter
配置为与ObjectMapper
具有相同的日期格式来注册您自己的Gson
。
答案 3 :(得分:0)
我在使用较新版本的 Spring 时遇到了类似的问题。我尝试使用 new ObjectMapper().writeValueAsString(...)
,但在我的情况下不起作用。
我实际上有一个 JSON 格式的 String
,但我觉得它实际上是将每个字段的 toString()
方法转换为 JSON。就我而言,日期 LocalDate
字段最终会是:
"date":{"year":2021,"month":"JANUARY","monthValue":1,"dayOfMonth":1,"chronology":{"id":"ISO","calendarType" :"iso8601"},"dayOfWeek":"FRIDAY","leapYear":false,"dayOfYear":1,"era":"CE"}
这不是在请求中发送的最佳日期格式...
最后,就我而言,最简单的解决方案是使用 Spring ObjectMapper
。它的行为更好,因为它使用 Jackson 构建具有复杂类型的 JSON。
@Autowired
private ObjectMapper objectMapper;
我只是在测试中使用了它:
mockMvc.perform(post("/api/")
.content(objectMapper.writeValueAsString(...))
.contentType(MediaType.APPLICATION_JSON)
);