Mocking a REST call with MockRestServiceServer

2020-02-11 01:48发布

问题:

I'm trying to write a JUnit test case which tests a method in a helper class. The method calls an external application using REST and it's this call that I am trying to mock in the JUnit test.

The helper method makes the REST call using Spring's RestTemplate.

In my test, I create a mock REST server and mock REST template and instanitiate them like this:

@Before
public void setUp() throws Exception {
    mockServer = MockRestServiceServer.createServer(helperClass.getRestTemplate());
}

I then seed the mock server so that it should return an appropriate response when the helper method makes the REST call:

// response is some XML in a String
mockServer
    .expect(MockRestRequestMatchers.requestTo(new URI(myURL)))
    .andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
    .andRespond(MockRestResponseCreators.withStatus(HttpStatus.OK)
        .contentType(MediaType.APPLICATION_XML)
        .body(response));

When I run my test, the helper method receives a null response from the REST call it makes and the test fails.

The REST URL that the helper makes has query params and looks like this: "http://server:port/application/resource?queryparam1=value1&queryparam2=value2".

I've tried putting the URL ("http://server:port/application/resource") both with and without the query parameters in the "myURL" variable (to elicit a match so that it returns a response), but can not get the mock server to return anything.

I've tried searching for examples of this kind of code but have yet to find anything which seems to resemble my scenario.

Spring version 4.1.7.

Thanks in advance for any assistance.

回答1:

When you create an instance of MockRestServiceServer you should use existing instance of RestTemplate that is being used by your production code. So try to inject RestTemplate into your test and use it when invoking MockRestServiceServer.createServer - don't create new RestTemplate in your tests.



回答2:

Seems that you are trying to test the rest-client, the rest-server should be tested in other place. You are using RestTemplate -> To call the service. Then, tried to mock RestTemplate and its call's results.

@Mock
RestTemplate restTemplateMock;

and Service Under Test Class

@InjectMocks
Service service;

Let say, Service has a method to be test as

public void filterData() {
   MyResponseModel response = restTemplate.getForObject(serviceURL, MyResponseModel.class);
   // further processing with response
}

Then, to test filterData method, you need to mock the response from restTemplate call such as

mockResponseModel = createMockResponse();
Mockito.when(restTemplateMock.getForObject(serviceURL, MyResponseModel.class)).thenReturn(mockResponseModel);

service.filterData();
//Other assert/verify,... go here


回答3:

You can create a new instance of RestTemplate however you have to pass it in your createServer method like this:

private RestTemplate restTemplate = new RestTemplate();
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
mockServer = MockRestServiceServer.createServer(restTemplate);
client.setRestTemplate(restTemplate);
}