【问题标题】:How to mock RestTemplate with Client or Server errors?如何使用客户端或服务器错误模拟 RestTemplate?
【发布时间】:2017-08-09 17:26:17
【问题描述】:

我在我的代码中使用了restTemplate.postForEntity()。 在围绕它测试类时,我使用 Mockito 来模拟 RestTemplate。

Mockito.when(restTemplate.postForEntity(.....)).thenReturn(response)

响应在哪里:

ResponseEntity<String> response = new ResponseEntity(HttpStatus.UNAUTHORIZED);

现在,当我运行此测试时,postForEntity 返回我刚刚显示的模拟响应。但是,在实际执行中,RestTemplate 在从远程接收到401 时会抛出RestClientException

这是因为RestTemplate 中的doExecute() 检查错误并在出现4XX 和5XX 错误时抛出此异常。

我当然可以重写模拟规则:

Mockito.when(restTemplate.postForEntity(.....)).thenThrow(new RestClientException(..)).

但是在阅读测试时,这不是很直观:我希望它本身响应 401 或 500。

我应该怎么做才能做到这一点?

【问题讨论】:

  • 如果你模拟RestTemplate,那么要走的路是thenThrow(new RestClientException(..)(注意你也可以使用真正的RestTemplate和mock the Http server

标签: java spring mockito resttemplate


【解决方案1】:

您已经在问题中说过:您正在模拟 RestTemplate 并测试使用它的类。你不是在嘲笑它,只是在嘲笑它。

如果您希望 RestTemplate 根据它接收到的 http 状态抛出该异常,那么您需要模拟 RestTemplate 使用的内部客户端,并使其在调用时返回该状态代码。然后你的 RestTemplate 应该被存根(或使用真正的实现)来响应那个 http 状态。

但在我看来这不是你想要测试的。

如果您只谈论测试的可读性(但继续测试您正在测试的内容),那么我建议创建一个基于 http 状态生成模拟答案的方法。如果状态不是 200,那么答案应该抛出异常。

因此,在您的 resttemplate 模拟中,您将拥有:

when(restTemplate.postForEntity(...))
    .thenAnswer(answer(401));

并回答类似的实现:

private Answer answer(int httpStatus) {
    return (invocation) -> {
        if (httpStatus >= 400) {
            throw new RestClientException(...);
        }
        return <whatever>;
    };
}

这只是一个例子,您需要适应您的特定需求。

【讨论】:

  • 我可能会更进一步,并基于 RestTemplate 用来确保您处理预期异常的DefaultErrorDecoder 的答案
【解决方案2】:

你可以尝试使用 Spring 内置的测试库,比如这里:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/client/MockRestServiceServer.html

这样你就可以模拟你调用的端点

【讨论】:

    猜你喜欢
    • 2016-11-06
    • 2014-10-31
    • 2017-03-17
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多