3

Good Afternoon to the experts,

I have a requirement where I will be invoking sequential calling of 3 REST APIs as part of a single client call GET /offers to retrieve offers available for each product in different aisles of a department store as below

  1. Get all the aisles in a department store /aisels
  2. Get all the products in an aisle /aisles/{aisleID}/products
  3. Get all the offers for the product /product/{productId/offers

    To do this from my @Service class using the RestTemplate exchange method:

    ResponseEntity aisles= restTemplate.exchange(url, HttpMethod.GET, requestEntity, Aisles.class);

Then retrieve each aisleId in a loop and invoke the 2nd API to get the Products

ResponseEntity<Products> products= restTemplate.exchange(url,
                    HttpMethod.GET, requestEntity, Products.class);

Then retrieve each productId in a loop and invoke the 3rd API to get the Offers

Finally collate all the responses to send the list of offers to the client.

Now, I am new to mockito framework for writing the JUnits. And my service class got a single method named retrieveAllOffers() in which I have the 3 exchange methods as above.

I was wondering how could I mock these 3 calls in my Junit to get a successful response scenario.

Your help is highly appreciated.

codeLover
  • 2,571
  • 1
  • 11
  • 27
BKA
  • 119
  • 1
  • 6
  • Check my [`answer`](https://stackoverflow.com/questions/57364351/ambiguous-method-call-mocking-resttemplate-exchange/57365466#57365466) here for an example on how to mock the `restTemplate#exchange` method. If you need anything more specific then add some code example of your class/method under test to your question. – second Aug 21 '19 at 07:52

1 Answers1

5

Instead of mocking the rest template you can mock the response of the service only. To do that you can use Wiremock ( http://wiremock.org/) which provides an api to stub calls on specific URLS and mock their responses to whatever you like and verify that they were called.

For your case you would need 3 stubs, one for each exchange. For example for this method restTemplate.exchange(url, GET, requestEntity, Products.class); that you provided a stub would look like

stubFor(get(urlEqualTo("yourUrl"))
  .willReturn(aResponse()
    .withStatus(200)
    .withBody(new ObjectMapper().writeValueAsString(yourResponseObject)
    .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE))

note that your url will need to point its server where wiremock is running ( if you use the java dependency and junit rule it will be localhost:wiremockPort )

the setup is pretty straight forward as you need to add a single rule to your test

@Rule public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort()); have a look here for the configure of the rule http://wiremock.org/docs/configuration/

and in the end you verify that your stubs where called with

verify(getRequestedFor(urlEqualTo("/yourUrl"))
  .withRequestBody(equalTo(new ObjectMapper().writeValueAsString(theObjectThatShouldBePosted))));

Hope that helped!

Michael Michailidis
  • 1,002
  • 1
  • 8
  • 21
  • Greetings Michael, thanks heaps for the answer. I tried to implement this and reading the URL from the application-test.properties file under the src/test/resources folder but for some reason the value is not being read and I tried the following options https://stackoverflow.com/questions/29669393/override-default-spring-boot-application-properties-settings-in-junit-test/29682080 but still not helpful. Any idea why my properties file is not being loaded? Thanks. – BKA Aug 24 '19 at 06:37
  • You are trying to get the service location from the properties in test right? You propably try to load in the test class! when you run a test with spring boot, spring will look for application-test.(properties|yaml) in the root of your test resources file and load it. Now instead of getting the url in your test you should take the configuration file of the main code. meaning your service / services in your main code look for this configuration externally and load it with a properties class. that means you can inject that class in your test also! – Michael Michailidis Aug 24 '19 at 08:57
  • Greetings Michael, sorry for the delay in responding. it was the issue with initialization of the implementation class because of which the properties are not reading. I have now used @Autowired annotation to auto initialize that so it working perfectly fine. Thanks again for your timely help. I have accepted the answer. – BKA Aug 28 '19 at 03:03
  • No worries ! if you need anything i would be glad to help you if i can. ( also just to mention it . accepting the answer requires to press the check under the flags so people will see this one was the solution have a look at this : https://stackoverflow.com/help/someone-answers ) – Michael Michailidis Aug 28 '19 at 07:25
  • Greetings Michael, sorry I am new to this. Just checked it. – BKA Sep 03 '19 at 07:16
  • Greetings Michael, it is possible to answer this? https://stackoverflow.com/questions/57767273/invoking-rest-api-using-spring-resttemplate-with-json-response-as-pojo-will-degr – BKA Sep 03 '19 at 08:10