【问题标题】:Kotlintest with Mockk How to clear verify countKotlintest 与 Mockk 如何清除验证计数
【发布时间】:2019-12-22 07:01:01
【问题描述】:

所以我有以下代码:

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 情况之前重置该计数?

【问题讨论】:

  • clear 方法应该可以帮助您重置计数。 wasNot Called 也可能对您有所帮助。至于你的第二个问题,哪个框架提供了when和then?
  • 我的测试扩展的 Kotlintest BehaviorSpec 为 BDD 提供了具有 Given、When、Then 的工具。

标签: unit-testing kotlin bdd mockk kotlintest


【解决方案1】:

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

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


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

默认isolationMode 是IsolationMode.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()
    }

}

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

【讨论】:

    【解决方案2】:
    1. 您应该尝试提供的各种clear 方法来重置模拟的状态。查看this related question 和MockK's docs 了解更多信息。

    2. 检查documentation about test listeners。基本上,每个测试规范类都提供了像beforeEach 这样的生命周期方法,您可以覆盖这些方法来重置您的模拟(使用clear)。在扩展 BehaviourSpec 时,您应该能够只覆盖这些方法,否则请确认如何为不同的 testing styles 执行此操作以避免混淆。

    【讨论】:

      【解决方案3】:

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

      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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        • 2015-08-03
        • 1970-01-01
        相关资源
        最近更新 更多