我在代码中使用了
restTemplate.postForEntity()
。
在测试围绕它的类时,我使用 Mockito 来模拟 RestTemplate。
Mockito.when(restTemplate.postForEntity(.....)).thenReturn(response)
响应是:
ResponseEntity<String> response = new ResponseEntity(HttpStatus.UNAUTHORIZED);
现在,当我运行此测试时,
postForEntity
返回我刚刚显示的模拟响应。然而,在实际执行中,RestTemplate 在从远程接收到 RestClientException
时会抛出 401
。
在幕后,这是因为
doExecute()
中的 RestTemplate
检查错误并在出现 4XX 和 5XX 错误时抛出此异常。
我当然可以重写模拟规则:
Mockito.when(restTemplate.postForEntity(.....)).thenThrow(new RestClientException(..))
.
但是在阅读测试时,这不是很直观:我希望它本身响应 401 或 500。
我应该怎么做才能实现这个目标?
您已经在问题中说过:您正在嘲笑 RestTemplate 并测试使用它的类。你不是在嘲讽,只是在嘲笑。
如果您希望 RestTemplate 根据其接收到的 http 状态抛出该异常,那么您需要模拟 RestTemplate 使用的内部客户端,并使其在调用时返回该状态代码。然后你的 RestTemplate 应该被存根(或使用真正的实现)来对该 http 状态做出反应。
但在我看来这不是你想要测试的。
如果您只谈论测试的可读性(但继续测试您正在测试的内容),那么我建议创建一个基于http状态生成mockito答案的方法。如果状态不是 200 那么答案应该抛出异常。
所以,在你的resttemplate模拟中你会:
when(restTemplate.postForEntity(...))
.thenAnswer(answer(401));
并回答实施类似:
private Answer answer(int httpStatus) {
return (invocation) -> {
if (httpStatus >= 400) {
throw new RestClientException(...);
}
return <whatever>;
};
}
这只是一个例子,您需要适应您的具体需求。
您可以尝试使用Spring内置的测试库,如下所示:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/client/MockRestServiceServer.html
这样你就可以模拟你调用的端点
我们可以这样模拟,这将返回 HttpClientErrorException ,错误代码为 401。
when(restTemplate.postForEntity(url,new HttpEntity<>.
(authHeader()),String.class))
.thenThrow(new HttpClientErrorException(HttpStatus. UNAUTHORIZED));