Spock执行实际而不是模拟

时间:2019-07-19 08:15:08

标签: unit-testing groovy spock

我在调用DeployArtifacts的类中具有以下方法:

def call(List artifacts) {
    String methodName = "deployStream${artifactType.toString()}"

    for (artifact in artifacts) {
        "methodName"(artifact)
    }
}

def deployStreamSOA(Map artifactDetails) {
    String artifactName = getDownloadArtifactName(artifactDetails)
    String targetName = getDownloadArtifactTarget(artifactDetails)
    String modifiedConfigFileName = getUpdatedConfigFileName(artifactName)
    deployArtifact(artifactName, targetName, modifiedConfigFileName)
}

我正在尝试通过以下测试来检查是否调用了deployStreamSOA:

def "type is SOA then deployStreamSOA is called"() {
    setup:
    def artifactList = [[groupId: "com.company", artifactId: "artifact1", version: "1.0.0"]]
    DeployArtifacts deployArtifacts = Spy(DeployArtifacts, constructorArgs: [ArtifactType.SOA]) {
        deployStreamSOA(_ as Map) >> ""
    }

    when:
    "DeployArtifact call is passed the SOA ArtifactType"
    deployArtifacts.call(artifactList)

    then:
    "the deployStreamSOA method is called"
    1 * deployArtifacts.deployStreamSOA(_)
}

但是它正在执行实际的deployStreamSOA方法。

我认为这可能与动态方法名称的生成有关,因此我尝试将其更改为常规方法调用,但仍然具有相同的响应。

如果我也模拟了deployStreamSOA方法中的方法,那么它将通过,并返回模拟值。

为什么不模拟deployStreamSOA,而是模拟其他方法?

如何在不模拟此调用的所有内部方法的情况下使它正常工作?

1 个答案:

答案 0 :(得分:1)

为了修复您的应用程序代码并使其实际调用预期的方法,请更改

"methodName"(artifact)

进入

"$methodName"(artifact)

更新:关于为何调用原始方法而不是存根间谍方法的实际说明,请参见Spock手册Combining Mocking and Stubbing章中的说明。许多Spock新手都犯了一个错误,甚至一些经验丰富的用户有时也会忘记它:

  

同一方法调用的模拟和存根必须在同一交互中发生。

即您可以像这样修复测试:

package de.scrum_master.stackoverflow.q57108265

import spock.lang.Specification

class DeployArtifactsTest extends Specification {
  def "type is SOA then deployStreamSOA is called"() {
    setup:
    def artifactList = [[groupId: "com.company", artifactId: "artifact1", version: "1.0.0"]]
    DeployArtifacts deployArtifacts = Spy(constructorArgs: [ArtifactType.SOA])

    when:
    "DeployArtifact call is passed the SOA ArtifactType"
    deployArtifacts.call(artifactList)

    then:
    "the deployStreamSOA method is called"
    1 * deployArtifacts.deployStreamSOA(_) >> ""
  }
}