简体   繁体   English

Kotlintest with Mockk 如何清除验证计数

[英]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 方法。

  1. How to reset smsRepository verify count?如何重置 smsRepository 验证计数?
  2. How to reset that count before every When case?如何在每个 When 案例之前重置该计数?

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 .默认的isolationModeIsolationMode.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.但我不确定这在您的用例中如何工作。

  1. 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 的文档以获取更多信息。

  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM