How do I mock a REST server with with multiple endpoints in the same test in Java?
Asked Answered
C

2

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?

Crease answered 17/11, 2017 at 23:5 Comment(5)
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.Electioneer
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.Crease
@AdvillPill Okay, well a good short term fix could be to just run two MockRestServiceServers, each of which has their own endpoint.Electioneer
@Shn_Android_Dev, I tried doing that already. It appears that creating a new MockRestServiceServer instance overrides the previous one.Crease
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.Bacillary
C
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.

Crease answered 18/11, 2017 at 21:16 Comment(0)
B
-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.

Bevon answered 17/11, 2017 at 23:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.