如何使用MockRestServiceServer测试RestClientException

JMa*_*rky 13 java spring mocking mockserver

在测试RestClient-Implementation时,我想模拟一个RestClientException,它可能被该实现中的一些RestTemplate方法引发了删除方法:

@Override
public ResponseEntity<MyResponseModel> documentDelete(String id) {
    template.setErrorHandler(new MyResponseErrorHandler());
    ResponseEntity<MyResponseModel> response = null;
    try {
        String url = baseUrl + "/document/id/{id}";
        response = template.exchange(url, DELETE, null, MyResponseModel.class, id);
    } catch (RestClientException ex) {
        return handleException(ex);
    }
    return response;
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

我用这种方式定义了mock-server:

@Before
public void setUp() {
    mockServer = MockRestServiceServer.createServer(template);
    client = new MyRestClient(template, serverUrl + ":" + serverPort);
}
Run Code Online (Sandbox Code Playgroud)

MaD*_*aDa 8

您可以测试抛出运行时异常MockRestServiceServer,尽管从Spring 5.0.0.RC4开始,此类不是为它设计的(这意味着它可能不适用于更复杂的用例):

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

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

它似乎在测试中起作用:

  • 那里只有一个RestTemplate电话,
  • 由于最后的期望而抛出异常的地方.

我无法期待连续两次例外; 的MockRestSeriviceServer(更具体的,所述SimpleRequestExpectationManager)抛出IllegalStateException上重放所述第二期望.


Ale*_*can 6

您可以利用MockRestResponseCreators模拟来自嘲笑服务服务器的4xx或5xx响应。

例如,测试5xx-内部服务器错误:

mockServer.expect(requestTo("your.url"))
                .andExpect(method(HttpMethod.GET/POST....))
                .andRespond(withServerError()...);
Run Code Online (Sandbox Code Playgroud)

你的情况RestClientException抛出用于客户端的HTTP错误,所以上面的例子中可以被微调用于4xx通过使用异常: ...andRespond(withBadRequest());...andRespond(withStatus(HttpStatus.NOT_FOUND));

为了更简单地使用这些方法,您可以将静态导入用于org.springframework.test.web.client.MockRestServiceServerorg.springframework.test.web.client.response.MockRestResponseCreators


eis*_*eis 5

Alex Ciocan的答案适用于不同的http状态响应,因此,如果需要这些响应,则不要这样做,因为这是最干净的方法。我有一个问题,我需要能够同时测试连接重置和其他网络级别的问题,这些问题很难模拟。

MaDa的回答适用于某些用例,但是使用AsyncRestTemplate时对我而言不起作用,因为它抛出得太早了。但是,这确实引导了我正确的方向。这个似乎也可以与异步调用一起使用:

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);
Run Code Online (Sandbox Code Playgroud)

这对于连续的异常以及不同的http状态似乎也适用。