[英]Kotlintest with Mockk How to clear verify count
So I have the following code:所以我有以下代码:
When("SMS with location update command is received") {
every {
context.getString(R.string.location_sms, any(), any(), any(), any())
} returns "loc"
mainServiceViewModel.handleSms(SmsMessage("123", "location"))
Then("SMS with location is sent to specified phone number") {
verify(exactly = 1) {
smsRepository.sendSms("+123", "loc")
}
}
}
When("motion is detected") {
Then("information SMS is sent to specified phone number") {
verify(exactly = 1) {
smsRepository.sendSms("+123", any())
}
}
}
The problem with it, that both cases pass, even though the second one doesn't do any action.它的问题是,两种情况都通过了,即使第二个没有做任何动作。 I expect second case to fail, as sendSms method is not even called.我希望第二种情况会失败,因为甚至没有调用 sendSms 方法。
This is probably due to the fact that KotlinTest is different from JUnit in what is considered a test and when a Spec
instance is created.这可能是因为 KotlinTest 与 JUnit 在被视为测试的内容以及创建Spec
实例时不同。
The default behavior for KotlinTest
is to create a single instance of the Spec
per execution. KotlinTest
的默认行为是在每次执行时创建Spec
的单个实例。 Due to this, your mocks are not getting reset between executions, as you probably have them created at class level
.因此,您的模拟不会在执行之间重置,因为您可能在class level
创建了它们。
To fix this, what you can do is either do the mockk
inside the test, or change the isolation mode to something that creates the Spec
every time a test is executed.要解决此问题,您可以做的是在测试中进行mockk
,或者将隔离模式更改为每次执行测试时都创建Spec
模式。
The default isolationMode
is IsolationMode.SingleInstance
.默认的isolationMode
是IsolationMode.SingleInstance
。 You can change it on the Spec
itself by overriding the isolationMode
function:您可以通过覆盖isolationMode
功能在Spec
本身上更改它:
class MySpec : BehaviorSpec() {
init {
Given("XX") {
Then("YY") // ...
}
}
override fun isolationMode() = IsolationMode.InstancePerTest
}
You can also change it in a ProjectConfig.您也可以在 ProjectConfig 中更改它。 If you need explanation on how to do it there, check the docs on ProjectConfig如果您需要有关如何在那里执行此操作的说明, 请查看 ProjectConfig 上的文档
An alternative would be to clear mocks on the afterTest
method:另一种方法是清除afterTest
方法上的afterTest
:
class MySpec : BehaviorSpec() {
init {
Given("XX") {
Then("YY") // ...
}
}
override fun afterTest(testCase: TestCase, result: TestResult) {
clearAllMocks()
}
}
But I'm not sure how that would work in your use-case.但我不确定这在您的用例中如何工作。
You should try the various clear
methods that are provided to reset the state of mocks.您应该尝试提供用于重置模拟状态的各种clear
方法。 Check this related question and MockK's docs for more information.查看此相关问题和MockK 的文档以获取更多信息。
Check the documentation about test listeners .检查有关测试侦听器的文档。 Basically, every test spec class provides lifecycle methods like beforeEach
, which you could override to reset your mocks (using clear
).基本上,每个测试规范类都提供了像beforeEach
这样的生命周期方法,你可以重写这些方法来重置你的beforeEach
(使用clear
)。 As you are extending BehaviourSpec, you should be able to just override those methods, otherwise confirm how to do this for different testing styles to avoid confusion.当您扩展 BehaviourSpec 时,您应该能够只覆盖这些方法,否则请确认如何针对不同的测试样式执行此操作以避免混淆。
To clear mocks after every test, you can provide a project wide listener:要在每次测试后清除模拟,您可以提供一个项目范围的侦听器:
import io.kotest.core.listeners.TestListener
import io.kotest.core.spec.AutoScan
import io.kotest.core.test.TestCase
import io.kotest.core.test.TestResult
import io.mockk.clearAllMocks
@AutoScan
class MockkClearingTestListener : TestListener {
override suspend fun afterEach(testCase: TestCase, result: TestResult) = clearAllMocks()
}
This works eg for every leaf in a WordSpec
, and should work for BehaviorSpec
as well.这适用于例如WordSpec
每个叶子,并且也适用于BehaviorSpec
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.