junit 在Kotlin中为单元测试分配“瓦尔”

uz75evzq  于 2023-02-04  发布在  Kotlin
关注(0)|答案(1)|浏览(112)

我正在用Kotlin写单元测试,为此我需要给一个“val”赋值,下面是代码的简化版本:

@Entity
@Table(name = "Request")
data class Request(

    @Column(name = "Name")
    val name: String,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    var id: Long? = null

    @CreationTimestamp
    @Column(name = "Created")
    val created: LocalDateTime = LocalDateTime.now()
}

@Test
fun `test one`() {
    val name = RandomStringUtils.randomNumeric(10)
    val id = Random.nextLong(100)
    val created = LocalDateTime.now().minusHours(48)
    
    val request = Request(playerUid = playerUid).apply {
        id = id
        created = created
    }
}

在测试中赋值“created”时出现编译错误。由于我需要设置我想要的“created”值,我应该如何管理这个单元测试?(我不能接触“Request类”的任何部分)

72qzrwbm

72qzrwbm1#

如果不能更改Request类的任何部分,则将无法更改created
您需要使用近似测试范围来测试createdcreated需要为0〈now〈2s之类的值)
LocalDateTime.now()这样的函数编码一个静态访问器是一个设计缺陷--这应该在服务类的外部设置。如果你真的做不到,那么这里有另一个黑客方法:
1.在某个地方添加一个CLOCK对象(不需要在伴随对象中),但最终必须更改created赋值:

@Entity
@Table(name = "Request")
data class Request(
    @Column(name = "Name")
    val name: String,
) {
    companion object {
        /** used for carrying a Clock only in the case of tests **/
        val CLOCK = ThreadLocal<Clock>()
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    var id: Long? = null

    @CreationTimestamp
    @Column(name = "Created")
    val created: LocalDateTime = LocalDateTime.now(CLOCK.get() ?: Clock.systemUTC())
}

通常情况下,您不会触及CLOCK,但在单元测试中,您定义了

private val fixedClock = Clock.fixed(Instant.parse("2022-08-29T08:20:50Z"), ZoneOffset.UTC)

那么你需要

@BeforeEach
fun beforeEach() {
    // this is necessary because the serialization of MemberMentorCommon.weeksOnPlan uses a clock
    CLOCK.getOrSet { fixedClock }
}

@AfterEach
fun afterEach() {
    CLOCK.remove()
}

是的,ThreadLocals是令人讨厌的,但是这允许您更改Request类的行为以覆盖now()函数

相关问题