25

I am trying to mock a POST method with MockRestServiceServer in the following way:

MockRestServiceServer server = bindTo(restTemplate).build();
server.expect(requestTo("/my-api"))
        .andExpect(method(POST))
        .andRespond(withSuccess(expectedResponce, APPLICATION_JSON));

Problem: How do I verify a request body in this setup?

I browsed through the documentation and some examples and still can't figure out how it can be done.

Sasha Shpota
  • 9,436
  • 14
  • 75
  • 148
  • Why do you want to check the request body? This is input data, which should not be verified. Is it just typo and you meant response body? – Igor Khvostenkov Aug 05 '19 at 12:34
  • @IgorKhvostenkov it is a POST requests which means it sends a piece of data. I want to verify that the information that is sent is correct. – Sasha Shpota Aug 05 '19 at 13:42
  • 2
    I don't think you are doing it right, if you are trying to verify request body, you only need to test how you create the body, not mocking the Api and test what was sent by you there... – stacker Aug 05 '19 at 21:58
  • This really does not matter if this is GET or POST. Conceptually, this is strange to test something which you manually define as correct or as wrong, but is not decided by production code. You can use approach @user7294900 has proposed, but more as narrowing the scope of your mock or having a more precise trigger, but not as verification of your production code. – Igor Khvostenkov Aug 05 '19 at 22:14
  • @IgorKhvostenkov maybe "verify" is not the best word here. Let me elaborate. I am writing an integration test. I do not want to hit a real API from the test, instead I am mocking the API. But if I do not check a request body the mocked API will return a successful response for all requests which is something I don't want. – Sasha Shpota Aug 06 '19 at 10:09
  • Ok, I've got your idea, posted example how I would do this. – Igor Khvostenkov Aug 06 '19 at 15:34

3 Answers3

20

You can use content().string to verify body:

.andExpect(content().string(expectedContent))

Or content().bytes:

this.mockServer.expect(content().bytes("foo".getBytes()))

this.mockServer.expect(content().string("foo"))

Community
  • 1
  • 1
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
0

How I would do such kind of test. I would expect on the mocked server the proper body to be received in String format and if this body has been received, the server will respond with the proper response body in String format. When I receive the response body, I would map it to the POJO and check all the fields. Also, I would map the request from String to POJO before send. So now we could check that mappings work in both directions and we can send requests and parse responses. Code would be something like this:

  @Test
  public void test() throws Exception{
    RestTemplate restTemplate = new RestTemplate();
    URL testRequestFileUrl = this.getClass().getClassLoader().getResource("post_request.json");
    URL testResponseFileUrl = this.getClass().getClassLoader().getResource("post_response.json");
    byte[] requestJson = Files.readAllBytes(Paths.get(Objects.requireNonNull(testRequestFileUrl).toURI()));
    byte[] responseJson = Files.readAllBytes(Paths.get(Objects.requireNonNull(testResponseFileUrl).toURI()));
    MockRestServiceServer server = bindTo(restTemplate).build();
    server.expect(requestTo("http://localhost/my-api"))
          .andExpect(method(POST))
          .andExpect(content().json(new String(requestJson, "UTF-8")))
          .andRespond(withSuccess(responseJson, APPLICATION_JSON));

    UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl("http://localhost/my-api");

    ObjectMapper objectMapper = new ObjectMapper();
    EntityOfTheRequest body = objectMapper.readValue(requestJson, EntityOfTheRequest.class);

    RequestEntity.BodyBuilder bodyBuilder = RequestEntity.method(HttpMethod.POST, uriBuilder.build().toUri());
    bodyBuilder.accept(MediaType.APPLICATION_JSON);
    bodyBuilder.contentType(MediaType.APPLICATION_JSON);
    RequestEntity<EntityOfTheRequest> requestEntity = bodyBuilder.body(body);

    ResponseEntity<EntityOfTheResponse> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<EntityOfTheResponse>() {});
    assertThat(responseEntity.getBody().getProperty1(), is(""));
    assertThat(responseEntity.getBody().getProperty2(), is(""));
    assertThat(responseEntity.getBody().getProperty3(), is(""));
  }
Igor Khvostenkov
  • 714
  • 5
  • 15
0

May use HttpMessageConverter can help. according to the document, HttpMessageConverter::read method can be the place that provide check the input ability.