繁体   English   中英

Jenkins-spock:方法存根失败取决于平台

[英]Jenkins-spock : method stub fails depending on the platform

这是我写的一段(简化的)代码和相关的单元测试,直到最近我都很高兴。

文件 vars/deleteFile.groovy

@NonCPS
def call(String path) {
    new File(path).delete() //Must be declared as authorized class & method in Jenkins
}

文件 vars/toto.groovy:

def call(Map params = [:] ) {
...
    deleteFile(params.get('envFile'))
...
}

文件测试/vars/TotoSpec.groovy:

class TotoSpec extends JenkinsPipelineSpecification {

    def toto = null

    def setup() {
        toto = loadPipelineScriptForTest('vars/toto.groovy')
        ...
    }

    def '[toto] test env file'() {
        when:
        toto envFile: 'env.list'

        then:
        ...
        1 * getPipelineMock('deleteFile.call').call('env.list')
    }

}

该测试曾经在我的本地机器和 CI 从站上通过。 但是,我不知道为什么,这在我的本地机器上开始失败(但不是在从机上):

java.lang.IllegalStateException: 
There is no pipeline step mock for [deleteFile.call].
        1. Is the name correct?
        2. Does the pipeline step have a descriptor with that name?
        3. Does that step come from a plugin? If so, is that plugin listed as a dependency in your pom.xml?
        4. If not, you may need to call explicitlyMockPipelineStep('deleteFile.call') in your test's setup: block.
        at TotoSpec.[toto] test env file(TotoSpec.groovy:90)

因此,我对我的单元测试执行了以下更新,但我不确定deleteFile是否真的是一个管道步骤,因为它没有正文/闭包。

文件测试/vars/TotoSpec.groovy:

class TotoSpec extends JenkinsPipelineSpecification {

    def setup() {
        toto = loadPipelineScriptForTest('vars/toto.groovy')
        explicitlyMockPipelineStep('deleteFile')
        ...
    }

    def '[toto] test env file'() {
        when:
        toto envFile: 'env.list'

        then:
        ...
        1 * getPipelineMock('deleteFile').call('env.list')
    }

}

现在单元测试在我的本地机器上正常,但在 CI 从站上失败:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Mock Generator for [deleteFile]' with class 'com.homeaway.devtools.jenkins.testing.PipelineVariableImpersonator' to class 'groovy.lang.Closure'
    at TotoSpec.setup(TotoSpec.groovy:32)

我错过了什么?

本地配置:

$ java --version
openjdk 14.0.2 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 14.0.2+12-Ubuntu-120.04, mixed mode, sharing)

mvn --version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 14.0.2, vendor: Private Build, runtime: /usr/lib/jvm/java-14-openjdk-amd64
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "4.19.128-microsoft-standard", arch: "amd64", family: "unix"

CI 从站配置:

$ java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Debian-1bpo91)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Debian-1bpo91, mixed mode)
$ /home/jenkins/tools/hudson.tasks.Maven_MavenInstallation/Maven_3.6.3/apache-maven-3.6.3/bin/mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /home/jenkins/tools/hudson.tasks.Maven_MavenInstallation/Maven_3.6.3/apache-maven-3.6.3
Java version: 11.0.6, vendor: Debian, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: fr_FR, platform encoding: UTF-8
OS name: "linux", version: "4.9.0-14-amd64", arch: "amd64", family: "unix"

pom.xml 中的依赖

 <properties>
        <groovy.core.version>2.4.17</groovy.core.version>
        <groovy.gmaven.pluginVersion>1.6.1</groovy.gmaven.pluginVersion>
        <google.guava.version>20.0</google.guava.version>

        <jenkins-spock.version>2.0.0</jenkins-spock.version>
        <jenkins.version>2.102</jenkins.version>
        <jenkins.servlet.version>3.1.0</jenkins.servlet.version>
        <jenkins.workflow.cps.version>2.36</jenkins.workflow.cps.version>
        <jenkins.workflow.basic.steps.version>2.6</jenkins.workflow.basic.steps.version>
        <jenkins.workflow.durable.task.step.version>2.21</jenkins.workflow.durable.task.step.version>
        <jenkins.workflow.stage.step.version>2.3</jenkins.workflow.stage.step.version>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <junit.version>4.12</junit.version>
        <junit.plugin.version>1.24</junit.plugin.version>
        <surefire.pluginVersion>2.22.0</surefire.pluginVersion>

        <logback.configration>logback-test.xml</logback.configration>
        <logdir>${project.build.directory}/log</logdir>
        <test.loglevel>ERROR</test.loglevel>
        <log.logback.version>1.2.3</log.logback.version>
        <log.slf4j.version>1.7.25</log.slf4j.version>
    </properties>
...
<dependencies>
        <dependency>
            <groupId>com.homeaway.devtools.jenkins</groupId>
            <artifactId>jenkins-spock</artifactId>
            <version>${jenkins-spock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${log.logback.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${log.logback.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jenkins-ci.main</groupId>
            <artifactId>jenkins-core</artifactId>
            <version>${jenkins.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jenkins-ci.plugins.workflow</groupId>
            <artifactId>workflow-basic-steps</artifactId>
            <version>${jenkins.workflow.basic.steps.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jenkins-ci.plugins.workflow</groupId>
            <artifactId>workflow-cps</artifactId>
            <version>${jenkins.workflow.cps.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <!-- provides sh() step -->
            <groupId>org.jenkins-ci.plugins.workflow</groupId>
            <artifactId>workflow-durable-task-step</artifactId>
            <version>${jenkins.workflow.durable.task.step.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <!-- provides stage() step -->
            <groupId>org.jenkins-ci.plugins</groupId>
            <artifactId>pipeline-stage-step</artifactId>
            <version>${jenkins.workflow.stage.step.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${jenkins.servlet.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jenkins-ci.plugins</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.plugin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>${groovy.core.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${log.slf4j.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>${log.slf4j.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

再次仔细阅读文档,因为deleteFile是我自己在vars目录下声明的,所以认为它是一个Pipeline Shared Library全局变量。

因此,切换到以下单元测试现在可以在任何地方正常工作:

class TotoSpec extends JenkinsPipelineSpecification {

    def setup() {
        toto = loadPipelineScriptForTest('vars/toto.groovy')
        explicitlyMockPipelineVariable('deleteFile')
        ...
    }

    def '[toto] test env file'() {
        when:
        toto envFile: 'env.list'

        then:
        ...
        1 * getPipelineMock('deleteFile.call').call('env.list')
    }
}

不过,目前还不清楚为什么我突然需要在我的机器上explicitlyMockPipelineVariable('deleteFile')使用explicitlyMockPipelineVariable('deleteFile')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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