如何使用 OffsetDateTime 属性测试数据类的相等性?
Posted
技术标签:
【中文标题】如何使用 OffsetDateTime 属性测试数据类的相等性?【英文标题】:how to test equality of data class with OffsetDateTime attribute? 【发布时间】:2021-12-13 21:05:04 【问题描述】:我在 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
)
【问题讨论】:
您能添加您要测试的代码吗?谢谢! @JoãoDias 我添加了正在测试的(琐碎的)控制器代码,还添加了withArgs
解决方法,这仍然太麻烦了
@Stuck 我试图让最小的复制运行,但您的代码中的某些内容没有对齐。您的 toEntity
函数需要一个不可为空的 Long
并且没有默认值,但是在您的实现和测试中,您没有将任何值作为参数传递。此外,该函数根本不使用参数userId
。你会这么好心,把代码调整成可运行的吗?
【参考方案1】:
tl;dr
将此添加到您的application.properties
:
spring.jackson.deserialization.adjust-dates-to-context-time-zone=false
这样,偏移量将被反序列化为检索到而不是更改。
我创建了一个(稍作修改)复制存储库on GitHub。在 Controller 内部,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
对齐。
【讨论】:
以上是关于如何使用 OffsetDateTime 属性测试数据类的相等性?的主要内容,如果未能解决你的问题,请参考以下文章
H2 数据库 - Java 的 OffsetDateTime 和 h2 类型之间的映射
在 Spring Boot 和 MongoDB 中使用 OffsetDateTime 会导致 MappingException
当时间需要在本地时间保持不变时,在 Java 中使用 OffsetDateTime 处理夏令时,而不管 DST
Spring Boot Rest - OffsetDateTime 作为浮点数返回