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.
This is probably due to the fact that Kotest is different from JUnit in what is considered a test and when a Spec
instance is created.
The default behavior for Kotest
is to create a single instance of the Spec
per execution. Due to this, your mocks are not getting reset between executions, as you probably have them created at 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.
The default isolationMode
is IsolationMode.SingleInstance
. You can change it on the Spec
itself by overriding the isolationMode
function:
class MySpec : BehaviorSpec() {
init {
Given("XX") {
Then("YY") // ...
}
}
override fun isolationMode() = IsolationMode.InstancePerTest
}
You can also change it in a ProjectConfig. If you need explanation on how to do it there, check the docs on ProjectConfig
An alternative would be to clear mocks on the afterTest
method:
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.