如何使用 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: -
在语义上,startDate
s 匹配,但时区不同。我想知道如何强制 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:00
或 Z
,类似于 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
。
我在 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: -
在语义上,startDate
s 匹配,但时区不同。我想知道如何强制 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:00
或 Z
,类似于 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
。