Search code examples
jsonspring-bootintegration-testingokhttpmockserver

MockServer and OkHttp: body type missmatch (json vs string)


Hi Stack Overflow community!

I'm trying to mock a microservice in some java integration tests.

To do so, I'm using MockServer version 5.5.1. To do the rest-requests I'm using OkHttp version 3.13.1

The code in java:

final SomeDTO requestObject = new SomeDTO(someParams);
final String jsonObject = objectMapper.writeValueAsString(requestObject);
final MediaType MEDIA_TYPE_JSON = MediaType.get("application/json; charset=utf-8");

final RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, jsonObject);
final Request request = new Request.Builder().url("serverUrl").post(requestBody).build();

final Response response = client.newCall(request).execute();
final String responseJson = response.body().string();
final ResultDTO result = objectMapper.readValue(responseJson, ResultDTO.class);

This works fine. However, when I attach MockServer with the matcher:

 final MockServerClient client = new MockServerClient("127.0.0.1", 1080);
 client.when(request().withMethod("POST") //
                      .withPath("serverUrl") //
                      .withBody(json(correctJsonString, MatchType.ONLY_MATCHING_FIELDS))) //
       .respond(response().withStatusCode(200) //
                          .withHeaders(new Header("Content-Type", "application/json; charset=utf-8"),
                                        new Header("Cache-Control", "public, max-age=86400"))
                          .withBody(responseJson));

I get a request didn't match expectation because: body didn't match, where the difference between the bodies are:

Request:

"body" : {
  "type" : "STRING",
  "string" : "{\"id\":33611,\"prop1\":28,\"prop2\":\"value2\",\"graph\":[...]}",
  "contentType" : "text/plain; charset=utf-8"
}

Request should match:

"body" : {
  "type" : "JSON",
  "json" : "{\"prop2\":\"value2\",\"prop1\":28,\"graph\":[...]}"
}

So my questions:

  • Is it correct to assume that because of the type "JSON" <-> "STRING", the body doesn't match?
  • Is this a wrong interpretation of MockServer or does OkHttp generate the wrong request? (The request itself does work)
  • Any suggestions how to fix this?

Solution

  • Here is a JSON Demo:

        @Test
    public void testRemote3() {
        String host = "localhost";
        int port = 1080;
        String url = String.format("http://%s:%d",host,port);
        MockServerClient mockServerClient = new MockServerClient(host,port);
        mockServerClient.when(
                request()
                        .withMethod("POST")
                        .withPath("/order/completed/notify")
                        .withBody(new JsonBody("{\"username\":\"foo1\", \"age\": 13}", Charset.forName("UTF-8"),MatchType.STRICT))
        ).respond(
                response().withStatusCode(200)
                        .withCookie("sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW")
                        .withHeader("Location", "https://www.mock-server.com")
                        .withBody("{\"username\":\"wang\", \"status\": 1}")
        );
        mockServerClient.when(
                request()
                        .withMethod("POST")
                        .withPath("/order/completed/notify")
                        .withBody(new JsonBody("{\"username\":\"zhao\", \"age\": 3}", Charset.forName("UTF-8"),MatchType.STRICT))
        ).respond(
                response().withStatusCode(200)
                        .withCookie("sessionId", "2By8LOhBmaW5nZXJwcmludCIlMDAzMW")
                        .withHeader("Location", "https://www.mock-server.com")
                        .withBody("{\"username\":\"wang\", \"status\": true}")
        );
        log.info("----------------->calling ");
        Map<String,Object> userInfo = new HashMap<>();
        userInfo.put("age",13);
        userInfo.put("username","foo1");
        String result = OkHttpUtils.postJson(url+"/order/completed/notify",userInfo);
        log.info(result);
        Map<String,Object> fool = new HashMap<>();
        fool.put("age",3);
        fool.put("username","zhao");
        result = OkHttpUtils.postJson(url+"/order/completed/notify",fool);
        log.info(result);
    }