web-dev-qa-db-ja.com

Spring MockMVCを使用してSpringの@RequestBodyをテストする

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
}

だから私の質問は次のとおりです。SpringMockMVCを使用してこの方法をテストする方法は?

43
Matt

これを使用してください

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リクエスト本文の構造に関する詳細情報

58
Priyanka Gupta

私のために次の作品、

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

問題は、アプリケーションがJSONをJackson GsonMappingJackson2HttpMessageConverter内)でデシリアライズしようとしている間に、カスタムObjectMapperオブジェクトで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"])

とりわけスタックトレース。

1つの解決策は、Gson日付形式を上記のいずれかに設定することです(スタックトレースで)。

別の方法は、ObjectMapperと同じ日付形式を持つように独自のGsonを構成することにより、独自のMappingJackson2HttpMessageConverterを登録することです。