簡體   English   中英

Mockito.mock 何時創建部分模擬而不是“完整”模擬?

[英]When does Mockito.mock create a partial mock instead of a “full” mock?

鑒於此代碼:

// Subject.kt

open class Subject(var x: Int) {

    constructor(): this(42) {
        println("made it")
    }

    fun doit() {
        x += 1
        println("did it: $x")
    }
}
// Tests.kt

import org.junit.jupiter.api.Test
import org.mockito.Mockito

class Tests {
    @Test
    fun makeit() {
        val mock = Mockito.mock(Subject::class.java)

        val details = Mockito.mockingDetails(mock)
        println("Is mock: ${details.isMock}")
        println("Is spy:  ${details.isSpy}")

        mock.doit()
        mock.doit()
    }
}

運行makeit時,output 為:

Is mock: true
Is spy:  false
did it: 1
did it: 2

這似乎表明正在創建主題的某些實例,但繞過了潛在的關鍵構造函數邏輯。 這與“部分模擬”是一致的,但代碼並沒有做任何事情來請求這樣的事情。

我發現這是默認行為令人驚訝,因為文檔都強烈警告不要使用部分模擬。 我一直無法找到描述mock()何時返回部分模擬的文檔,因此無法弄清楚如何從 class 獲得“完整模擬”。

所以:

  • Mockito.mock()何時創建部分模擬?
  • Mockito 可以為 class 創建“完整模擬”嗎? 還是只是為了一個界面?
  • 如何請求“完整模擬”?

通過源代碼和反復試驗,我得出以下結論:

  1. When mocking a class, Mockito creates an instance of a ByteBuddy-generated subclass of the class without calling the constructor => all member data is default values.
  2. 打開方法(Java 的默認值;在 Kotlin 中用open聲明):
    • 默認情況下調用並返回返回類型的默認值。
    • 將在配置時調用when(...).thenCallRealMethod()
    • 如果創建 mock 時將defaultAnswer設置為CALLS_REAL_METHODS將被調用
  3. final方法不能被覆蓋 => 它們將被正常調用,但它們將看到所有成員數據的默認值。

因此,似乎所有 class 模擬都是部分模擬,但由於 Java 中的默認值是打開方法,它們通常看起來像常規模擬。 默認情況下,它們實際上是常規模擬。

這在 Kotlin 中很快出現,因為默認情況下方法是final的。

知道這是如何工作的,處理 class 模擬就不那么令人沮喪了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM