Kotlin中带OffsetDateTime属性的data class相等性测试方案
方案1:统一JSON序列化/反序列化时区配置
问题的根源是Spring Boot默认的Jackson配置会将请求传入的带偏移量的时间强制调整为服务端上下文的时区(默认是UTC),导致反序列化后的OffsetDateTime和你构造的测试对象偏移量不一致,equals判定失败。你可以通过修改Jackson全局配置保留原偏移量:
@Configuration class JacksonConfig { @Bean fun objectMapper(): ObjectMapper { return ObjectMapper() .registerModule(JavaTimeModule()) // 禁止自动调整时间到上下文时区 .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) } }
配置后反序列化得到的OffsetDateTime会保留请求中携带的偏移量,不需要修改测试逻辑即可通过coVerify的相等校验。
方案2:统一Entity层的时间存储格式
如果业务不需要保留请求端传入的时区偏移,直接在DTO转Entity的逻辑里把所有OffsetDateTime统一转为UTC时区,从根源避免时区差异:
fun toEntity(): SomeEntity { return SomeEntity( id = id, // 保留瞬时时间不变,偏移量统一转为UTC startDate = startDate.withOffsetSameInstant(ZoneOffset.UTC), ) }
构造测试预期值时也同步转为UTC时区即可,该方案同时可以避免数据库存储、跨时区业务交互的时间一致性问题。
方案3:自定义MockK参数匹配规则
如果不想修改业务代码,只调整测试逻辑,可以按需选择匹配方式:
单测试字段匹配
使用match或withArg结合OffsetDateTime的语义相等判断方法:
coVerify { someService.save(match { it.id == expectedToStore.id && it.startDate.isEqual(expectedToStore.startDate) }) }
isEqual方法会比较两个时间的瞬时时间是否相等,忽略时区偏移差异。
全局OffsetDateTime语义匹配
给MockK注册全局相等判断器,所有OffsetDateTime的比较都自动用语义相等规则:
// 注册全局自定义相等判断 MockKPlatformStrategies.jvm.veryExperimentalEqualsChecker.register { a: OffsetDateTime, b: OffsetDateTime -> a.isEqual(b) } coVerify { someService.save(expectedToStore) }
注:该功能属于MockK的实验特性,后续版本API可能发生变动
内容的提问来源于stack exchange,提问作者Stuck
相关产品推荐
相关产品推荐

