iT邦幫忙

2021 iThome 鐵人賽

DAY 25
1
Modern Web

Kotlin 怎麼操作資料庫?談談 Kotlin Exposed 框架系列 第 25

[Day 25] 如果我們不想 mock Clock 怎麼辦呢?談依賴反轉

上次我們成功的撰寫好了 isValidDate(),並且利用 mockk 框架,來製作了一個假 Clock 固定測試時的時間。

不過,這段測試有沒有更簡單的實作方式呢?

有的,下面我們來提提,利用依賴反轉的原則,讓這段程式更加的簡潔

什麼是依賴反轉?

依賴反轉的觀念,首先要從什麼是依賴講起。

以我們的程式來舉例

fun isValidDate(): Boolean {
    val clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"))
    val now = LocalDateTime.now(clock)
    val dueDate = LocalDateTime.parse("2021-12-31T23:59:59")
    return dueDate.isAfter(now)
}

要取的現在時間,我們透過了 Clock 物件,讓 LocalDateTime 可以取得現在時間。所以 isValidDate() 要能取得現在時間,是需要透過 Clock 物件的。

如果這個邏輯是固定不變的,那麼這段程式沒什麼大問題。可是一旦這段程式需要調整,比方說我們在測試階段需要切換不同的 Clock,那就麻煩了。

所以反過來說,我們可以想辦法讓取得時間不是依賴 Clock.fixed(Instant.now(),ZoneId.of("UTC")) 建立的一個 Clock 物件,而是一個外部傳進來,和 Clock 類別有相同方法的物件,我們就可以既確保程式的邏輯正確,又保有足夠的彈性,可以在需求改變時切換取得時間的方式。

我們調整一下 isValidDate()

fun isValidDate(clock: Clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"))): Boolean {  
    val now = LocalDateTime.now(clock)  
    val dueDate = LocalDateTime.parse("2021-12-31T23:59:59")  
    return dueDate.isAfter(now)  
}

這邊我們將 clock 移動到參數,並給予一個預設值。在多數的情境下,我們要取得的邏輯都是現在時間,所以 clock 預設為 Clock.fixed(Instant.now(), ZoneId.of("UTC")))

在測試程式碼內,我們的 在2022-01-01時應該回傳false 可以改成

fun `在2022-01-01時應該回傳false`() {
	val fixedClock = Clock.fixed(
		Instant.parse("2022-01-01T23:59:59Z"),
		ZoneId.of("UTC")
	)
	assertThat(isValidDate(fixedClock), `is`(false))
}

不利用 mock 的方式,就能抽換掉 isValidDate() 裏面的時間,更加直觀了。

同樣的方式也能修改 在2021-12-30時應該回傳true

fun `在2021-12-30時應該回傳true`() {  
    val fixedClock = Clock.fixed(  
        Instant.parse("2021-12-30T23:59:59Z"),  
 ZoneId.of("UTC")  
    )  
    assertThat(isValidDate(fixedClock), `is`(true))  
}

這樣,我們的測試就成功調整完成了!


上一篇
[Day 24] 新功能又來了!時間相關的測試!
下一篇
[Day 26] review 一下我們的程式,談談 DSL 和 DAO 的差異
系列文
Kotlin 怎麼操作資料庫?談談 Kotlin Exposed 框架30

尚未有邦友留言

立即登入留言