当前位置: 首页 > 知识库问答 >
问题:

TestRestTemplate引发4xx状态代码异常

应子真
2023-03-14

我正在为一个Spring-Boot应用程序编写组件测试,以测试我的安全配置。因此,我正在运行测试,应该测试成功的响应以及“禁止”状态。我遇到的问题是,由于我的REST调用需要一个复杂的JSON,对于阻塞的调用,测试会失败,因为TestRestTemplate试图反序列化不存在的响应体。

我正在运行一个Spring-Boot应用程序,tests类的注释如下:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

我试图测试一个应该返回用户列表的REST API。该呼叫的简化版本为:

ResponseEntity<List<User>> responseEntity  = testRestTemplate.exchange(URL, HttpMethod.GET, entity, new ParameterizedTypeReference<List<User>>() {});

其中TestRestTemplate由Spring autowired,实体包含授权信息。

对于未经授权的请求,我将得到如下错误:

org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List<my.package.User>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token
 at [Source: (PushbackInputStream); line: 1, column: 1]

如果我将响应实体更改为receive String而不是List,我将收到响应,并可以检查状态,看到它是“禁止的”。

ResponseEntity<String> responseEntity  = testRestTemplate.exchange(URL, HttpMethod.GET, null, String.class);

我知道我可以通过以下方法来解决这个问题:

  • 使用字符串和Gson反序列化,或
  • 使用RestTemplate而不是TestRestTemplate并处理HttpStatusCodeException或
  • 在状态代码不是2xx时重写不尝试反序列化的方法

但是由于TestRestTemplate应该是一个容错方便的子类,所以我希望它是开箱即用的,而不是尝试对错误响应进行反序列化。

我是不是漏掉了什么?我用错了吗?

共有1个答案

澹台衡
2023-03-14

很抱歉再次出现这个将近2年的问题,但是我在使用SpringTestrestTemplate和阴性验证测试时遇到了非常类似的问题。

正如Martin在回答中提到的,TestRestTemplate不包括通常与正确的RESTTemplate关联的ResponseErrorHandler。但是响应的正文仍然包含错误消息,而不是用户列表。

在我的例子中,我的Web应用程序有@ControllerAdvise,它包装了所有常见的验证错误(MethodArgumentNotValidExceptionMethodArgumentTypeMismatchException等)并返回了我自己的类ErrorMessagedTo的实例。控制器将把它封送到JSON而不是预期的响应。

我的组件测试最初试图捕获HttpStatusCodeException,因为这是由正常的RestTemplate引发的。在测试中,没有引发异常(因为缺少ResponseErrorHandler),而我的RestTemplate.PostForObject(path,request,MyResponse.class)只是返回了MyResponse的空版本。

在阅读了马丁的描述和下面的链接后,我将其改为

ResponseEntity<ErrorMessageDto> responseEntity = restTemplate.postForEntity(path, request, ErrorMessageDto.class);

// Do assertions on the response code and body (using assertj)
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.UNPROCESSABLE_ENTITY);
assertThat(responseEntity.getBody().getErrors())
                .extracting("path", "message")
                .contains(tuple("firstName", "size must be between 0 and 255"))

在您的例子中,我确信您返回的错误消息是错误消息类的实例。您可能通过返回字符串并手动编组的建议实现了这一点。如果您知道错误消息表示的是什么类,您可以简单地将其替换为responseEntity中的类型。

 类似资料:
  • 问题内容: 这是我的用法- 另外,我在http GET周围放置了一个finally块- 这是我的堆栈跟踪- 我正在使用Quartz计划监视Http端点的工作。这是我的连接池配置 Maven依赖..工件版本 编辑 -好吧,通过不关闭finally块中的CloseableHttpClient,问题解决了。有人能说出为什么这样吗? 如果关闭客户端,为什么连接池会关闭? 是上面的closeablehttp

  • 我想返回200以外的HTTP状态,而不使用注释。 这样做的原因是,并不是每次调用我的应用程序(导致状态为not OK)都应该抛出异常,至少在我看来不是这样。 例如,如果一个用户试图登录系统,但提供了一个不准确的密码,我认为没有理由为了能够返回401状态而抛出异常。相反,我希望能够从“常规”方法中返回状态。 这背后的原因是,抛出不必要的异常既弄乱了我的日志文件,又“使用”了我的日志聚合器(Rollb

  • 调用此获取操作时: 会引发一个异常...我的全局exc处理程序被触发。 当我的自定义响应返回给客户端时,我的小提琴手总是说: 结果:200 我还可以更改<code>返回Ok(数据)to

  • 我正在尝试使用简单的Spring MVC项目,但我对Tom Cat有例外 类型异常报告 servlet MVC的消息servlet.init()-Dispatcher引发异常 说明服务器遇到内部错误,导致它无法完成此请求。 我的控制器: My Home.jsp

  • 我正在学习Spring MVC,当我试图运行html文件时,它会给出错误HTTP Status 500-引发异常 这是我的web.xml 这是我的Spring调度员Servlet 这是我的jsp页面 这是我的HelloController课程 这是我得到的一个例外 我正在使用Eclipse 4.5.1、Tomcat 8.0.30和Spring 4.2.3。