Kotlintest with Mockk 如何清除验证计数

Kotlintest with Mockk How to clear verify count

所以我有以下代码:

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())
            }
        }
    }

它的问题是,两种情况都通过了,即使第二种情况没有执行任何操作。我预计第二种情况会失败,因为甚至没有调用 sendSms 方法。

  1. 如何重置 smsRepository 验证计数?
  2. 如何在每个 When 案例之前重置该计数?
  1. 您应该尝试提供的各种 clear 方法来重置模拟状态。查看 and MockK's docs 了解更多信息。

  2. 勾选documentation about test listeners. Basically, every test spec class provides lifecycle methods like beforeEach, which you could override to reset your mocks (using 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以避免混淆。

这可能是因为 KotlinTest 在被视为测试以及创建 Spec 实例时不同于 JUnit。

KotlinTest 的默认行为是每次执行创建 Spec 的单个实例。因此,您的模拟不会在执行之间重置,因为您可能在 class level.

处创建了它们

要解决此问题,您可以做的是在测试中执行 mockk,或者将 isolation mode 更改为每次执行测试时都会创建 Spec 的内容.

默认 isolationModeIsolationMode.SingleInstance。您可以通过覆盖 isolationMode 函数在 Spec 本身上更改它:

class MySpec : BehaviorSpec() {

    init {
        Given("XX") { 
            Then("YY") // ...
        }
    }

    override fun isolationMode() = IsolationMode.InstancePerTest

}

您也可以在 ProjectConfig 中更改它。如果您需要有关如何操作的说明,check the docs on ProjectConfig


另一种方法是清除 afterTest 方法上的模拟:

class MySpec : BehaviorSpec() {

    init {
        Given("XX") { 
            Then("YY") // ...
        }
    }

    override fun afterTest(testCase: TestCase, result: TestResult) {
        clearAllMocks()
    }

}

但我不确定这在您的用例中如何运作。

要在每次测试后清除模拟,您可以提供项目范围的侦听器:

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()
}

这有效,例如对于 WordSpec 中的每片叶子,也应该适用于 BehaviorSpec