7

I'm trying to test a Java method that makes a request to a remote REST server to retrieve some JSON data, extracts an ID from that JSON, then uses the ID to make another request to the same server at a different endpoint.

Using Mockito's MockRestServiceServer, I can successfully mock and test a server that expects a single request to one endpoint, but it seems that I cannot use it to create a server with a set of predefined endpoints with their own expectations and responses.

How do I mock a server with multiple endpoints for the purpose of testing a single function that makes multiple, distinct requests to the remote server?

AdvilPill
  • 341
  • 2
  • 6
  • Even though I believe you've written your question coherently, I'm having a difficult time understanding why you can't just make multiple requests. Send out a request to the first endpoint, parse the JSON response, then submit a new request to one of the different endpoints with the previously parsed JSON, and repeat as many times as you need to. Mockito's MockRestServiceServer may have some code in their server's API that let's you do it, so maybe dig into their documentation. – Shane Sepac Nov 17 '17 at 23:20
  • 2
    I'm trying to test a single function in a web script that makes two API calls. As far as I can tell, I cannot pre-emptively define two endpoints on a MockRestServiceServer and then run the method so that both endpoints exist in the mock server when the function is called. – AdvilPill Nov 17 '17 at 23:30
  • @AdvillPill Okay, well a good short term fix could be to just run two MockRestServiceServers, each of which has their own endpoint. – Shane Sepac Nov 17 '17 at 23:33
  • 1
    @Shn_Android_Dev, I tried doing that already. It appears that creating a new MockRestServiceServer instance overrides the previous one. – AdvilPill Nov 17 '17 at 23:37
  • My point is, your service when call external api the order matter? if yes, the mockedCall need follow that order. Your answer is correct if the code(production) no care about the order. – Carlos Eduardo Jun 09 '21 at 18:27

2 Answers2

17

So I was actually able to solve my problem. The trick is to manually create your own MockRestServiceServerBuilder to build your MockRestServiceServer instead of using the createServer(RestTemplate) or bindTo(RestTemplate).build() methods, like so:

MockRestServiceServer.MockRestServiceServerBuilder builder = 
    MockRestServiceServer.bindTo(restTemplate);
builder.ignoreExpectOrder(true);
MockRestServiceServer server = builder.build();

By doing so, the underlying RequestExpectationManager field in the MockRestServiceServer is initialized as an UnorderedRequestExpectationManager, allowing you to match requests regardless of the order in which they were made. This solved a lot of headaches for me.

AdvilPill
  • 341
  • 2
  • 6
-2

My answer assumes you are using SpringBoot but the idea can be applied generically.

Make your class depend on the RestOperations interface so that you can pass a stub when testing.

Class Under Test

public class Foo {
  private final RestOperations restOperations;

  public Foo(RestOperations restOperations) {
    this.restOperations = restOperations;
  }
}

Test

  public void test() {
    Foo foo = new Foo(new MyStub());
  }

Depend on abstractions, not concrete implementations.

Joe Deluca
  • 80
  • 5