gpt4 book ai didi

unit-testing - 基于 Spock 交互的测试 : too few invocation on a method

转载 作者:行者123 更新时间:2023-12-02 14:16:05 28 4
gpt4 key购买 nike

我有一个非常简单的方法。它调用另一个软删除 API key 的方法,然后调用另一个方法来创建一个新的并返回它。

测试也在下面,它只是检查这两种方法是否被正确调用。但是,尽管这两种方法仍然出现 0 调用错误。是什么导致了这个问题?

AuthApiKeyPair updateApiKeyPair(AuthApiKeyPair apiKeyPair, Boolean createNewKey) {

AuthApiKeyPair newKeyPair

if (createNewKey) {
deleteApiKeyPair(apiKeyPair)

//The key will be created with the same info as the previous key.
newKeyPair = createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)
}

newKeyPair
}

测试:
def "should soft delete key pair and create new one"() {
setup:
AuthApiKeyPair apiKeyPair = AuthApiKeyPair.build(acquirerId: 123, source: PaymentSource.BOARDING_API, label: 'Boarding API key')

when:
service.updateApiKeyPair(apiKeyPair, true)

then:
1 * service.deleteApiKeyPair(apiKeyPair)
1 * service.createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)
}

最佳答案

如果您考虑一下您的测试,您会意识到在最好的情况下,它测试的是 Spock 的模拟机制,而不是您的业务代码。您还没有向我们展示您的测试规范的完整类(class),但是根据您的场景,我们可以假设 service在你的测试中只是一个模拟。如果这是真的,那么你不能指望这两个调用:

then:
1 * service.deleteApiKeyPair(apiKeyPair)
1 * service.createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)

即将发生。仅仅因为模拟类不执行真正的方法。

我强烈建议您测试一个真正的类,而不是测试特定方法导致的调用类型,而是 调用特定方法的预期(和确定性)结果是什么 反而。你可以执行 service.updateApiKeyPair(apiKeyPair, true)when 中的真实对象上子句,然后您可以检查是否创建了新的 API key 对(并保存在您使用的存储中)以及旧的 key 对是否不再存在。与仅检查调用相比,此类测试至少有一些好处:
  • 您可以更改 service.updateApiKeyPair() 的实现在任何时候,只要它产生相同的结果,您的测试仍然有用(因为测试不会像调用测试那样限制您的实现),
  • 你测试实际行为而不是模拟库 - 有这个
    轶事说 Mockito 是数百万个项目中测试次数最多的库。

  • 当然,它可能需要一些设计更改。我猜测您的服务类使用了一些注入(inject)的 DAO 或存储 API key 对的存储库。考虑为您的测试提供这种 DAO 的内存实现 - 一个类,它不是在真实数据库中持久化对象,而是将所有对象存储在内部 ConcurrentMap<K,V> .多亏了这一点,您仍然可以将测试作为单元测试运行,并且您可以测试是否使用 createNewKey 更新 API key 对。参数设置为 true完全符合您的期望。或者,您可以编写一个带有 H2 数据库替换的集成测试,但这只会使您的测试 Bootstrap 更长。这是你的选择。

    有一条规则值得记住——如果您的类/组件/功能等难以进行单元测试,则意味着做出了错误的设计选择。

    替代方案:Spock 的 Spy对象

    我最后故意提到一件事。 Spock 支持所谓的“ spy ”对象,其行为类似于真实对象,但它们允许您 stub 某些部分并将该对象视为模拟对象,例如调用计数。但即使是 Spock 的作者也告诫开发人员不要使用此功能:

    (Think twice before using this feature. It might be better to change the design of the code under specification.)

    Source: http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#spies



    我不知道 Grails 是否有一个用于创建 Spy 而不是 Mock 的测试注释,但你总是可以 follow official documentation并创建简单的 Spock 单元测试,将您的服务实例化为 Spy,然后您可以尝试计算调用次数。我不建议这样做,只是为了记录而提及。

    关于unit-testing - 基于 Spock 交互的测试 : too few invocation on a method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51005634/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com