我有一个关于mockk
的问题。
当使用MockK的wasNot called
来检查是否调用了ClassA
时,即使在当前测试中没有调用ClassA
,如果在另一个测试中调用,也会出现测试失败的问题。
为什么会发生这种情况,我该如何解决?
代码:
class ClassA {
fun method(): Int = 1
}
class ClassB(val classA: ClassA, var call: Boolean = true) {
fun method(): Int = if(call) classA.method() else 0
}
class MyTest: FreeSpec({
"Test" - {
val mockClassA = mockk<ClassA>()
val sut = ClassB(mockClassA)
"methodA called" - {
every { mockClassA.method() } returns 1
sut.method()
verify { mockClassA.method() }
}
"methodA not called" - {
every { mockClassA.method() } returns 1
sut.call = false
sut.method()
verify { mockClassA wasNot called } // failed here
}
}
})
错误消息:
Verification failed: ClassA(#1) should not be called:
有几种方法可以绕过这种行为。
本地模拟
一种方法是不重用mock,而是为每个测试创建一个新的mock和一个新sut
。如果这会导致大量重复的代码,那么您只需为设置编写辅助函数即可。
隔离模式
您可以为Kotest测试定义不同的隔离模式。默认的是SingleInstance
,这意味着在测试类中运行测试时,只有一个规范被实例化。
当您将其更改为InstancePerLeaf
时,将为规范中的每个测试叶创建一个新的规范实例。您可以在不同的位置定义它,例如全局ProjectConfig
:
class ProjectConfig : AbstractProjectConfig() {
override val isolationMode = IsolationMode.InstancePerLeaf
}
或者在本地进行这样的测试:
class MyTest : FreeSpec({
isolationMode = IsolationMode.InstancePerLeaf
"Test" - {
...
透明模拟
您可以使用clearMocks
清除每个mock的内部状态,或者使用clearAllMocks
为所有mock清除内部状态。当您在每次测试后执行此操作时,验证不会因早期测试中的调用而失败。
你可以这样称呼它:
"methodA called" - {
every { mockClassA.method() } returns 1
sut.method()
verify { mockClassA.method() }
clearMocks(mockClassA)
}
或者对于所有这样的测试:
afterAny {
clearMocks(mockClassA)
}
"methodA called" - {
...