模拟验证wasNot调用失败



我有一个关于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" - {
...

最新更新