15

在测试 RestClient-Implementation 时,我想模拟一个 RestClientException,它可能由该实现中的某些 RestTemplate-methods 抛出,例如 delete-method:

@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;
}

我怎样才能做到这一点?

我以这种方式定义模拟服务器:

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

4 回答 4

14

您可以测试从 中抛出运行时异常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")); });

它似乎在测试中起作用:

  • 只有一个RestTemplate电话,
  • 由于最后的期望而引发异常的地方。

我无法期待连续两次例外。the MockRestSeriviceServer(更具体的, the SimpleRequestExpectationManager)抛出IllegalStateException了第二个期望。

于 2017-12-11T09:50:56.103 回答
11

您可以利用MockRestResponseCreators来模拟来自 mockRestServiceServer 的 4xx 或 5xx 响应。

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

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

4xx在您的情况下,客户端 HTTP 错误会引发 RestClientException,因此可以使用以下示例对异常进行 微调:...andRespond(withBadRequest());...andRespond(withStatus(HttpStatus.NOT_FOUND));

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

于 2017-03-03T11:21:15.770 回答
6

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);

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

于 2018-06-06T09:22:05.470 回答
0

这个怎么样 :

@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());
        }  
于 2019-09-11T20:56:53.753 回答