簡體   English   中英

帶有上下文接收器的 Mockk

[英]Mockk with context receiver

我正在嘗試使用 Mockk 來模擬帶有上下文接收器的方法:

class MyClass {
    // The method I'm going to mock
    context(CallContext)
    fun myMethod(a: Int) Int { a }
}

很難在單元測試中獲取 CallContext 的實例。 所以我希望我可以這樣寫一個單元測試:

/* 
This should work, but I can't get the CallContext instance 
with(callContextInstance) {
    Every { mockedMyClass.myMethod(1) } returns 2
}
*/

// I hope a unit test can be written like this... But it won't compile now.
with(any<CallContext>) {
    Every { mockedMyClass.myMethod(1) } returns 2
}

所以我該怎么做? 提前致謝。

在撰寫本文時,MockK不支持 context receivers ,並且可能要等到 context receivers 發布后才會支持——所以在 Kotlin 1.9 之后的某個時間,所以可能是在 2024 年)。

(上下文接收器被明確描述為尚未准備好生產。穩定版本將在 K2 發布之后發布,並且K2 beta 的目標是 Kotlin 1.9 ,計划於 2023 年 12 月發布。)

也就是說,如果有人想嘗試支持,那就堅持下去。MockK 是一個接受 PR 的社區支持的開源項目。

混雜因素

然而,在 MockK 完全支持上下文接收器之前有兩個障礙:

  • 上下文接收器尚未完成,它們當前的實現也不穩定。 KT-10468 它們的實施可能會發生重大變化。 嘗試實現對移動目標的支持具有挑戰性。
  • IDE 支持有限,這使得使用它們進行開發變得困難(請按照KTIJ-20857進行更新)

解決方法

同時,您可以調整代碼以允許手動模擬。

首先,將MyClass調整為一個開放類,或者引入一個新接口來描述您想要模擬的行為(接口代碼)。

/** Describe the API that [MyClass] will implement */
interface MyClassSpec {
  context(CallContext)
  fun myMethod(a: Int): Int
}

然后實現接口

/** Concrete implementation of [MyClassSpec] */
class MyClass: MyClassSpec {
  context(CallContext)
  override fun myMethod(a: Int): Int = a
}

現在在您的測試中,您可以通過創建一個實現MyClassSpec匿名對象來創建模擬 - 現在您有一個支持上下文接收器的模擬。

@Test
fun myTest() {
  val myClassMock = object : MyClassSpec {
    context(CallContext)
    override fun myMethod(a: Int): Int = 123
  }
}

如果我知道你到底想模擬什么,以下適用於 mockk 1.13.3:

interface CallContext

class MyClass {
    context(CallContext)
    fun myMethod(a: Int): Int = a
}

class ContextMockTest {
    private val myClassMock: MyClass = mockk()

    @Test
    fun mockContextWorks() {
        every {
            with(any<CallContext>()) {
                myClassMock.myMethod(any())
            }
        } returns 123

        val context = object : CallContext { }

        with(context) {
            assertEquals(123, myClassMock.myMethod(1))
        }

        verify {
            with(any<CallContext>()) {
                myClassMock.myMethod(1)
            }
        }
    }
}

以防萬一鏈接到要點

暫無
暫無

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

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