SMG*_*ost 9 bdd unit-testing kotlin mockk kotest
所以我有以下代码:
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())
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于,尽管第二个案例没有执行任何操作,但这两个案例都通过了。我预计第二种情况会失败,因为甚至没有调用 sendSms 方法。
这可能是因为 Kotest 与 JUnit 在测试的定义和实例的Spec创建时间上有所不同。
默认行为Kotest是创建Spec每次执行的单个实例。因此,您的模拟不会在执行之间重置,因为您可能在 处创建了它们class level。
要解决此问题,您可以做的就是在mockk测试内部进行,或者将隔离模式更改为每次执行测试时都会创建的隔离模式。Spec
默认isolationMode为IsolationMode.SingleInstance. Spec您可以通过覆盖该函数来更改它本身isolationMode:
class MySpec : BehaviorSpec() {
init {
Given("XX") {
Then("YY") // ...
}
}
override fun isolationMode() = IsolationMode.InstancePerTest
}
Run Code Online (Sandbox Code Playgroud)
您还可以在 ProjectConfig 中更改它。如果您需要有关如何执行此操作的说明,请查看 ProjectConfig 上的文档
另一种方法是清除该afterTest方法的模拟:
class MySpec : BehaviorSpec() {
init {
Given("XX") {
Then("YY") // ...
}
}
override fun afterTest(testCase: TestCase, result: TestResult) {
clearAllMocks()
}
}
Run Code Online (Sandbox Code Playgroud)
但我不确定这在您的用例中如何发挥作用。