Mark Bramnik
Mark Bramnik

Reputation: 42541

Testing MockRestServiceServer spring-test with multipart request

Recently I've started to use Spring's MockRestServiceServer to verify my RestTemplate based requests in tests.

When its used for simple get/post request - all good, however, I couldn't figure out how to use it with POST multipart request:

For example, my working code that I would like to test looks like this:

public ResponseEntity<String> doSomething(String someParam, MultipartFile 
   file, HttpHeaders headers) { //I add headers from request 

   MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
   map.add("file", new ByteArrayResource(file.getBytes()) {
            @Override
            public String getFilename() {
                return file.getOriginalFilename();
            }
        });
        map.add("someParam", someParam);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new 
             HttpEntity<>(map, headers);
        return this.restTemplate.exchange(
                  getDestinationURI(), 
                  HttpMethod.POST, 
                  requestEntity, 
                  String.class);
}

So my question is How I can specify my expectations with org.springframework.test.web.client.MockRestServiceServer? Please notice, that I don't want to just mock the "exchange" method with mockito or something, but prefer to use MockRestServiceServer

I'm using spring-test-4.3.8.RELEASE version

A code snippet would be really appreciated :)

Thanks a lot in advance

Update: As per James's request I'm adding non-working test snippet (Spock test):

MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build()
        server.expect(once(), requestTo(getURI()))
             .andExpect(method(HttpMethod.POST))
             .andExpect(header(HttpHeaders.CONTENT_TYPE, startsWith("multipart/form-data;boundary=")))

             .andExpect(content().formData(["someParam" : "SampleSomeParamValue", "file" : ???????] as MultiValueMap))
             .andRespond(withSuccess("sample response", MediaType.APPLICATION_JSON))

        multipartFile.getBytes() >> "samplefile".getBytes()
        multipartFile.getOriginalFilename() >> "sample.txt"

I get exception while asserting the request content. The form data is different, because an actual form data is created internally with Content-Disposition, Content-Type, Content-Length per parameter and I don't know how to specify these expected values

Upvotes: 3

Views: 6551

Answers (2)

Adam Michalik
Adam Michalik

Reputation: 9965

Multipart request expectations have been added to MockRestServiceServer in Spring 5.3 - see:

You can use

Parse the body as multipart data and assert it contains exactly the values from the given MultiValueMap. Values may be of type:

  • String - form field
  • Resource - content from a file
  • byte[] - other raw content

Variant of multipartData(MultiValueMap) that does the same but only for a subset of the actual values.

Upvotes: 1

Robert
Robert

Reputation: 2471

I think this depends on how deeply you want to test the form data. One way, which is not 100% complete, but is a "good enough" for unit testing (usually) is to do something like:

server.expect(once(), requestTo(getURI()))
       .andExpect(method(HttpMethod.POST))
        .andExpect(content().string(StringContains.containsString('paramname=Value') ))....

This is ugly and incomplete, but is sometimes useful. Of course, you can also work to make the form setup it's own method and then use mocks to try to verify that the expected parameters are all in place.

Upvotes: 1

Related Questions