问题描述
@RestController
@RequestMapping("/profiles",produces = [MediaType.APPLICATION_JSON_VALUE])
class Controller(@Autowired val restClient: RestClient) {
@GetMapping("/simple-get")
fun simpleGetCall(): List<Profile> {
restClient.callClientGet()
return listof(
Profile("firstname1","lastname1"),Profile("firstname2","lastname2"))
}
}
控制器正在调用正在发起客户端调用 (CODE) 的 RestClient
@Service
class RestClient(@Autowired val restTemplate: RestTemplate) {
fun callClientGet(){
try {
restTemplate.getForEntity(
"/profiles/simple-get",Number::class.java
)
}catch(exception: Exception){
throw MyClientCallException("this is an exception")
}
}
}
MyClientCallException 看起来像这样 (CODE)
class MyClientCallException(message: String) :
ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR,message)
我的班级有 3 个功能测试 (CODE)
我使用 org.springframework.test.web.client.MockRestServiceServer
作为服务器
@Test
fun `when calling service,and client returns Accepted,status should be OK`() {
val responseType: ParameterizedTypeReference<List<Profile>> =
object : ParameterizedTypeReference<List<Profile>>() {}
mockServer?.expect(MockRestRequestMatchers.requestTo(URI("http://localhost:8082/profiles/simple-get")))
?.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
?.andRespond(
MockRestResponseCreators.withStatus(HttpStatus.ACCEPTED)
.contentType(MediaType.APPLICATION_JSON))
val response = testRestTemplate.exchange(
"/profiles/simple-get",HttpMethod.GET,null,responseType
)
response.statusCode shouldBe HttpStatus.OK
response.body?.size shouldBe 2
}
此测试按预期进行。客户端返回 ACCEPTED
,服务器调用返回 List<Profile>
第二次测试失败。
@Test
fun `when calling service,and client timeout,it should return 500 - not working,problems with parsing`() {
val responseType: ParameterizedTypeReference<List<Profile>> =
object : ParameterizedTypeReference<List<Profile>>() {}
mockServer?.expect(MockRestRequestMatchers.requestTo(URI("http://localhost:8082/profiles/simple-get")))
?.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
?.andRespond(
MockRestResponseCreators.withStatus(HttpStatus.REQUEST_TIMEOUT)
.contentType(MediaType.APPLICATION_JSON))
val response = testRestTemplate.exchange(
"/profiles/simple-get",responseType
)
response.statusCode shouldBe HttpStatus.INTERNAL_SERVER_ERROR
}
当我进行客户端调用时,它会假装超时异常,这种情况总是会发生。
然后返回的 Exceptions
无法解析为 List<Profile>
,然后给出以下错误:
org.springframework.web.client.RestClientException: 时出错
提取类型 [java.util.List扩展模型。配置文件>]
和内容类型 [application/json];嵌套异常是
org.springframework.http.converter.HttpMessageNotReadableException:
JSON 解析错误:无法反序列化类型的值
java.util.ArrayList<model.Profile>
来自对象值(令牌
JsonToken.START_OBJECT
);嵌套异常是
com.fasterxml.jackson.databind.exc.MismatchedInputException:不能
反序列化 java.util.ArrayList<model.Profile>
类型的值来自
[来源:
(pushbackinputstream);行:1,列:1]
接下来的 2 个测试是变通方法,但对我来说都不好。
JsonToken.START_OBJECT
响应类型仍与原始类型相同。但它捕获了 RestClientException。 我期待抛出我的 MyClientCallException 并抓住它。 (它返回500,这很好,但我想看看自己的异常。这只是一个例子,也许我想返回不同的错误代码)
@Test
fun `when calling service,it should return 500 working `() {
val responseType: ParameterizedTypeReference<List<Profile>> =
object : ParameterizedTypeReference<List<Profile>>() {}
mockServer?.expect(MockRestRequestMatchers.requestTo(URI("http://localhost:8082/profiles/simple-get")))
?.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
?.andRespond(
MockRestResponseCreators.withStatus(HttpStatus.REQUEST_TIMEOUT)
.contentType(MediaType.APPLICATION_JSON))
assertThrows<RestClientException> {
testRestTemplate.exchange(
"/profiles/simple-get",responseType
)
}
}
第二个:我只是将所有内容解析为一个字符串,这有助于解决它。
但我最初正在等待一个 @Test
fun `when calling service,it should return 500 - but response type is wrong`() {
mockServer?.expect(MockRestRequestMatchers.requestTo(URI("http://localhost:8082/profiles/simple-get")))
?.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
?.andRespond(
MockRestResponseCreators.withStatus(HttpStatus.REQUEST_TIMEOUT)
.contentType(MediaType.APPLICATION_JSON))
val response = testRestTemplate.exchange(
"/profiles/simple-get",String::class.java
)
response.statusCode shouldBe HttpStatus.INTERNAL_SERVER_ERROR
}
所以,告诉 List<Profile>
,我只想要一个字符串作为响应会伪造测试。
有什么办法可以改善或解决这个问题吗?
您可以查看完整的项目:https://github.com/joergi/tryouts/tree/main/kotlin-mockrestserver 以获得更好的试用。
附言我知道,这个问题类似于Spring TestRestTemplate parse Error instead of HttpClientErrorException thrown,但仍然没有答案。
解决方法
然后返回的异常无法解析到列表,然后给出以下错误: - 您要求 jackson 将异常映射到配置文件列表,这显然是失败的。
为什么不使用响应类型作为 MyClientCallException 而不是 ParameterizedTypeReference ? - 这应该允许 jackson 将异常响应流解析为 MyClientCallException
另外,如果您想知道为什么 RestClientException
与其他客户端错误不同 - https://github.com/spring-projects/spring-framework/commit/b84fefc430cdf10d428b02f6d61009b7460ae26f#diff-309e077b6d47c54260c59a899971042456c5e03eb5e96e5121c31842b55deedb