如何使用 OffsetDateTime 属性测试数据 class 是否相等?

how to test equality of data class with OffsetDateTime attribute?

我在 DTO 和实体中有一个属性定义如下:

val startDate: OffsetDateTime,

dto 有一个 toEntity 方法:

data class SomeDTO(
  val id: Long? = null,
  val startDate: OffsetDateTime,
  ) {

    fun toEntity(): SomeEntity {
      return SomeEntity(
        id = id,
        startDate = startDate,
      )
    }
}

还有一个控制器

@RestController
@RequestMapping("/some/api")
class SomeController(
  private val someService: SomeService,
) {
  @PostMapping("/new")
  @ResponseStatus(HttpStatus.CREATED)
  suspend fun create(@RequestBody dto: SomeDTO): SomeEntity {
    return someService.save(dto.toEntity())
  }
}

我有一个失败的测试:

  @Test
  fun `create Ok`() {
    val expectedId = 123L

    val zoneId = ZoneId.of("Europe/Berlin")
    val dto = SomeDTO(
      id = null,
      startDate = LocalDate.of(2021, 4, 23)
        .atStartOfDay(zoneId).toOffsetDateTime(),
    )
    val expectedToStore = dto.toEntity()
    val stored = expectedToStore.copy(id = expectedId)

    coEvery { someService.save(any()) } returns stored

    client
      .post()
      .uri("/some/api/new")
      .contentType(MediaType.APPLICATION_JSON)
      .bodyValue(dto)
      .exchange()
      .expectStatus().isCreated
      .expectBody()
      .jsonPath("$.id").isEqualTo(expectedId)

    coVerify {
      someService.save(expectedToStore)
    }
  }

coVerify 的测试失败,因为 startDate 不匹配:

Verification failed: ...
... arguments are not matching:
[0]: argument: SomeEntity(id=null, startDate=2021-04-22T22:00Z),
matcher: eq(SomeEntity(id=null, startDate=2021-04-23T00:00+02:00)),
result: -

在语义上,startDates 匹配,但时区不同。我想知道如何强制 coVerify 对类型 OffsetDateTime 使用适当的语义比较,或者如何强制 OffsetDateTime= 的内部格式?或者我们应该使用什么其他方法来验证 expectedToStore 值传递给 someService.save(...) ?

我可以使用 withArgs 但它很麻烦:

coVerify {
  someService.save(withArg {   
    assertThat(it.startDate).isEqualTo(expectedToStore.startDate)
    // other manual asserts
 })
}

tl;dr

将此添加到您的 application.properties

spring.jackson.deserialization.adjust-dates-to-context-time-zone=false

这样,偏移量将在检索时被反序列化,而不是被更改。


我创建了一个(稍作修改的)复制存储库 on GitHub。在控制器内部,dto.startDate 的值已经是 2021-04-22T22:00Z,因此在 UTC。

默认情况下,使用“Jackson”的序列化库将反序列化期间的所有偏移量对齐到相同的配置偏移量。 使用的默认偏移量是 +00:00Z,类似于 UTC。

您可以通过 属性 spring.jackson.deserialization.adjust-dates-to-context-time-zone={true false} 启用/禁用此行为并使用 spring.jackson.time-zone=<timezone>

设置时区

或者,您可以在反序列化期间强制将偏移量与其他时区对齐:

spring.jackson.time-zone=Europe/Berlin

这样,偏移量将与时区对齐 Europe/Berlin