J'essaie de tester une méthode qui publie un objet dans la base de données à l'aide de la structure MockMVC de Spring. J'ai construit le test comme suit:
@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();
}
La méthode que je teste utilise @RequestBody de Spring pour recevoir l'ObjectBean, mais le test renvoie toujours une erreur 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;
}
Le json créé par gson dans le test:
{
"objectId":"33",
"userId":"4268321",
//... many more
}
La classe 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
}
Ma question est donc la suivante: comment tester cette méthode avec Spring MockMVC?
Utilisez celui-ci
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());
}
Comme décrit dans les commentaires, cela fonctionne car l'objet est converti en json et transmis en tant que corps de la demande. En outre, le contentType est défini en tant que Json (APPLICATION_JSON_UTF8).
Plus d'informations sur la structure du corps de la requête HTTP
ce qui suit fonctionne pour moi,
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);
}
}
Le problème est que vous sérialisez votre bean avec un objet personnalisé Gson
alors que l’application tente de désérialiser votre JSON avec un Jackson ObjectMapper
(dans MappingJackson2HttpMessageConverter
).
Si vous ouvrez les journaux de votre serveur, vous devriez voir quelque chose comme:
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"])
parmi d'autres traces de pile.
Une solution consiste à définir votre format de date Gson
sur l'un des formats ci-dessus (dans la pile).
L'alternative est d'enregistrer votre propre MappingJackson2HttpMessageConverter
en configurant votre propre ObjectMapper
pour qu'il ait le même format de date que votre Gson
.