-1

I am searching for a way to test a method, which sends a POST request to an external service. The application will NOT be itself a consumable webservice, that is why I didn't implement the shown class below as @RestController, @Controller, @Service, whatever types there may be.

But I don't know how to call the method postNumberPlate() to send a request to an embedded webserver (started in/by/at the unit test) to make some assertions on it. I want to avoid, to install an external webserver.

In other words: Can I start an embedded webserver inside a unit-test and 'tell' it to accept my POST request to inspect and assert the contents?

I already did:

  • a massive Webresearch (2-3 days?)
  • read Howto's
  • check the springboot docs
  • use an embedded Jetty Server (somehow blocking loop)
  • declare the Application as Webapplication and setting random port to jetty
  • experiment with Mockito, MockMVC
  • read "How to unittest a class using RestTemplate offline?" and compared it to my case, but found,
    • that it's very old (8y),
    • I don't know how to implement the parent interface, which is pretty huge
    • that the question and answers are too generic to deduce a solution for my case
    • it's not answering the embedded testing webserver problem I included.

The Class to be tested:

public class RestfulClient {

    private RestTemplate restTemplate = new RestTemplate();
    private HttpHeaders headers = new HttpHeaders();

    @Value("${kafkaeskadapter.uri}")
    private String destinationURL;

    public RestfulClient() {}

    public ResponseEntity<String> postNumberPlate(String key, CamImage camImage) {

        LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("numplate", camImage.getIdentifier());
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<LinkedMultiValueMap<String,
                Object>>(map, headers);

        ByteArrayResource resource = new ByteArrayResource(camImage.getData()) {
            /**
             * IMPORTANT!!! Otherwise I receive a BAD REQUEST
             * @return
             */
            @Override
            public String getFilename() {
                return camImage.getIdentifier() + ".png";
            }
        };
        map.add("image", resource);

        ResponseEntity<String> result = restTemplate.exchange(destinationURL, HttpMethod.POST,
                requestEntity, String.class);

        return result;
    }
}

I hope I could clarify my question a bit.

Semo
  • 783
  • 2
  • 17
  • 38
  • Just to be clear.. you want to do an integration test.. not a unit test right? Do you actually want to call restTemplate.exchange.. or just mock it/ – Maciej Kowalski Jul 04 '19 at 09:09
  • Good point. Maybe it's 1/2, perhaps 2/3 of an Integration test (because the method contacts an external webservice), though 1/3 is an unit test, because I'd like to see, whether the request contains a correct structure and of course to understand what spring spits out. So I need to call restTemplate.exchange(...). Because I want to offer the exchange() method an endpoint to sysout the received contents. :-) – Semo Jul 04 '19 at 09:28
  • Possible duplicate of [How to unittest a class using RestTemplate offline?](https://stackoverflow.com/questions/4643105/how-to-unittest-a-class-using-resttemplate-offline) – Raedwald Jul 04 '19 at 10:35
  • @Raedwald Sorry, but I don't think so. The OP's question and the answer is total generic and does not solve the issue I described. Also I don't think its a good idea to implement any huge parent interface of RestTemplate and blow up the code, because I can't oversee the side-effects of depending spring unit test helper classes. It's here about how to use a simple "webserver" object to offer it as an endpoint to check what was and how was it sent, to inspect and assert the message, without installing a fully fledged webserver. regards. – Semo Jul 04 '19 at 11:02

1 Answers1

0

A solution is to write a simple light-weight Webservice Endpoint and include it into your Run Configuration of your IDE. I made a separate mini project and would add further methods if needed, e.g. to accept different media.

Prior to run the actual unit tests, it is possible to configure the start of the Endpoint and return a meaningful ResponseEntity. The result can be inspected et voilà, assertions are possible.

A word about StackOverflow user arrogance: @Raedwald, after reading and trying, the answers in the linked question are not really helpful, but involve a lot of knowlegde about the stuff, and I have no one around of my colleagues, which could ever assist at programming. So it wasn't helpful to flag my question for deletion.

Semo
  • 783
  • 2
  • 17
  • 38