【问题标题】:HttpMessageNotWritableException in SpringBootTestSpringBootTest 中的 HttpMessageNotWritableException
【发布时间】:2020-05-02 14:23:02
【问题描述】:

我创建了一个控制器,它实际上在我的测试用例中以错误结束。我以相同的方式制作的其他控制器很少,并且测试可以正常工作。目前我正在寻找解决方案,但几个小时后我就被困住了。

以下测试用例失败,因为它导致 http 错误 500 而不是 200

@ActiveProfiles("Test")
@AutoConfigureMockMvc
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Transactional
@SpringBootTest


. . .
@Test
public void whenCreateCustomer_ThenReturnIt() throws Exception {
    String customerName = "foobar2";
    MvcResult result = mvc.perform(post(REST_CUSTOMERS)
            .header(HEADER_AUTH_KEY, authTokenAdminUser.getToken())
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\n" +
                    "  \"name\": \""+ customerName + "\"" +
                    "}")
    )
            .andExpect(status().isOk())
            .andReturn();

    String responseString = result.getResponse().getContentAsString();
    CustomerEntity customer = objectMapper.readValue(responseString, CustomerEntity.class);
    assertThat(customer).isNotNull();

    assertThat(customer.getName()).isEqualTo(customerName);
    assertThat(customer.getCreated()).isNotNull();
}

这是正在测试的方法。我已经调试过了,看起来不错。实体已经创建,并且它到达了 ResponseEntity 应该在其主体中返回 ok 的地步。我也评估了这个 return ResponseEntity.ok().body(createdCustomer.get());在调试器中,它工作了。

@Override
@PostMapping
public ResponseEntity<CustomerDTO> create(@RequestBody CustomerDTO dto) {
    dto.setId(uidService.getNextUidScServer());
    if (dto.getCreated() == null){
        dto.setCreated(LocalDateTime.now());
    }
    Optional<CustomerDTO> createdCustomer = customerService.create(dto);
    if (createdCustomer.isPresent()){
        return ResponseEntity.ok().body(createdCustomer.get());
    }
    else{
        return ResponseEntity.badRequest().build();
    }
}

在堆栈跟踪中我发现了这个,我认为这是我的问题。但我实际上不知道如何解决它。

Async:
  Async started = false
   Async result = null

  Resolved Exception:
          Type = org.springframework.http.converter.HttpMessageNotWritableException

这是实体

    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @Entity
    @Builder
    @Table(name = "Customer")
    public class CustomerEntity {


        @Id
        @Column(name = "uid")
        private Long id;

        @Column(name = "name")
        private String name;

        @Column(name = "created")
        private LocalDateTime created;

        @OneToMany(
                mappedBy = "customer",
                cascade = CascadeType.ALL,
                orphanRemoval = true)
        List<PenEntity> pen;

这里是 dto

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CustomerDTO {

        private Long id;
        private String name;

        @JsonDeserialize(using = LocalDateDeserializer.class)
        @JsonSerialize(using = LocalDateSerializer.class)
        private LocalDateTime created;

        @JsonIgnore
        private List<PenEntity> pen;
    }

从错误消息看来,json 映射存在问题。有什么想法吗?

【问题讨论】:

    标签: spring spring-boot spring-data-jpa


    【解决方案1】:

    对于消息转换器,您没有使用正确的Serializer。您必须使用LocalDateTimeSerializer 而不是LocalDateSerializer

    @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public class CustomerDTO {
    
            private Long id;
            private String name;
    
            @JsonDeserialize(using = LocalDateTimeDeserializer.class)
            @JsonSerialize(using = LocalDateTimeSerializer.class)
            private LocalDateTime created;
    
            @JsonIgnore
            private List<PenEntity> pen;
        }
    

    你说你使用了断点。以后如果遇到不理解的异常,在这个异常的构造函数中使用断点。然后,使用堆栈跟踪来识别哪个类抛出了异常,以及如何修复它。
    在我的调试器中,我看到了这个:

    “无法写入 JSON:类 java.time.LocalDateTime 无法转换为类 java.time.LocalDate(java.time.LocalDateTime 和 java.time.LocalDate 位于加载程序'bootstrap'的模块 java.base 中)”

    您也应该有吸气剂,但据我了解,来自 Lombok 的 @Data 会生成它们。所以你应该很好。

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 2016-08-18
      • 2021-08-13
      • 2018-04-09
      • 2018-10-31
      • 2019-05-15
      • 2014-10-24
      • 2021-02-07
      • 2022-10-13
      相关资源
      最近更新 更多