How to test a RestClientException with MockRestServiceServer

瘦欲@ 提交于 2019-12-04 00:57:41

You can take advantage of the MockRestResponseCreators for mocking 4xx or 5xx responses from the mockRestServiceServer.

For example for testing a 5xx - Internal server error:

mockServer.expect(requestTo("your.url"))
                .andExpect(method(HttpMethod.GET/POST....))
                .andRespond(withServerError()...);

In your case the RestClientException is thrown for client-side HTTP errors, so the example above can be fine tuned for a 4xx exception by using: ...andRespond(withBadRequest()); or ...andRespond(withStatus(HttpStatus.NOT_FOUND));

For a more simpler usage of these methods you use static imports for org.springframework.test.web.client.MockRestServiceServer,org.springframework.test.web.client.response.MockRestResponseCreators

You can test throwing runtime exceptions from the MockRestServiceServer, although this class, as of Spring 5.0.0.RC4, is not designed for it (which means it may not work for more complex use cases):

RestTemplate yourApi;
MockRestServiceServer server = MockRestServiceServer.createServer(yourApi);

server.expect(requestTo("http://..."))
    .andRespond((response) -> { throw new ResourceAccessException(
        new ConnectException("Connection reset")); });

It seems to work in tests:

  • where there's only one RestTemplate call,
  • where the exception is thrown as a result of the last expectation.

I wasn't able to expect two consecutive exceptions; the MockRestSeriviceServer (more concrete, the SimpleRequestExpectationManager) throws IllegalStateException on replaying the second expectation.

Answer by Alex Ciocan works for different http status responses, so if you want those, go with that as that's the cleanest way to go. I had a problem that I needed to be able to test also for connection reset and other network-level problems, which are trickier to simulate.

Answer by MaDa works for some use cases, but it didn't work for me when using AsyncRestTemplate, as it throws too early. However it did lead me to right direction. This one seems to work with async calls as well:

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

// ...

ClientHttpResponse exceptionThrowingResponse = mock(ClientHttpResponse.class);

when(exceptionThrowingResponse.getStatusCode()) // getRawStatusCode() in latest spring
    .thenThrow(new IOException("connection reset");

mockServer.expect(requestTo("http://localhost:123/callme"))
    .andRespond((response) -> exceptionThrowingResponse);

This seems to also work for consecutive exceptions, as well as different http statuses.

How about this :

@Spy
@InjectMocks
ClasstoMock objToMock;

@Test
public void testRestClientException() throws  Exception {       
        try {
        Mockito.when(this.objToMock.perform()).thenThrow(new RestClientException("Rest Client Exception"));
        this.objToMock.perform();
        }
        catch(Exception e){
            Assert.assertEquals(RestClientException.class, e.getClass());
        }  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!