jenkins - 模拟 Jenkins 管道步骤

标签 jenkins groovy mocking jenkins-pipeline

我在 jenkinsfile 中使用了一个类,这里​​是它的简化版本:

class TestBuild {
    def build(jenkins) {
        jenkins.script {
            jenkins.sh(returnStdout: true, script: "echo build")
        }
    }
}

我供应this在 jenkinsfile 中使用它时作为 jenkins 参数。在这里模拟具有 script 和 sh 的 jenkins 对象的最佳方法是什么?
谢谢你的帮助

最佳答案

前一周我遇到了类似的问题,我想出了这个:

import org.jenkinsci.plugins.workflow.cps.CpsScript

def mockCpsScript() {
    return [
        'sh': { arg ->
            def script
            def returnStdout
            // depending on sh is called arg is either a map or a string vector with arguments
            if (arg.length == 1 && arg[0] instanceof Map) {
                script = arg[0]['script']
                returnStdout = arg[0]['returnStdout']
            } else {
                script = arg[0]
            }
            println "Calling sh with script: ${script}"
        },
        'script' : { arg ->
              arg[0]()
        },
    ] as CpsScript
}

并与您的脚本一起使用(使用未命名的 sh 调用扩展):
class TestBuild {
    def build(jenkins) {
        jenkins.script {
            jenkins.sh(returnStdout: true, script: "echo build")
            jenkins.sh("echo no named arguments")
        }
    }
}

def obj = new TestBuild()
obj.build(mockCpsScript())

它输出:
[Pipeline] echo
Calling sh with script: echo build
[Pipeline] echo
Calling sh with script: echo no named arguments

现在这个它自己不是很有用,但是很容易添加定义模拟方法行为的逻辑,例如,这个版本控制 readFile 返回的内容,具体取决于正在读取的目录和文件:
import org.jenkinsci.plugins.workflow.cps.CpsScript

def mockCpsScript(Map<String, String> readFileMap) {
    def currentDir = null
    return [
        'dir' : { arg ->
            def dir = arg[0]
            def subClosure = arg[1]
            if (currentDir != null) {
                throw new IllegalStateException("Dir '${currentDir}' is already open, trying to open '${dir}'")
            }
            currentDir = dir
            try {
                subClosure()
            } finally {
                currentDir = null
            }
        },
        'echo': { arg ->
            println(arg[0])
        },
        'readFile' : { arg ->
            def file = arg[0]
            if (currentDir != null) {
                file = currentDir + '/' + file
            }
            def contents = readFileMap[file]
            if (contents == null) {
                throw new IllegalStateException("There is no mapped file '${file}'!")
            }
            return contents
        },
        'script' : { arg ->
              arg[0]()
        },
    ] as CpsScript
}

class TestBuild {
    def build(jenkins) {
        jenkins.script {
            jenkins.dir ('a') {
                jenkins.echo(jenkins.readFile('some.file'))
            }
            jenkins.echo(jenkins.readFile('another.file'))
        }
    }
}

def obj = new TestBuild()
obj.build(mockCpsScript(['a/some.file' : 'Contents of first file', 'another.file' : 'Some other contents']))

这输出:
[Pipeline] echo
Contents of first file
[Pipeline] echo
Some other contents

如果您需要使用 currentBuild 或类似的属性,那么您可能需要在闭包强制之后分配这些属性:
import org.jenkinsci.plugins.workflow.cps.CpsScript

def mockCpsScript() {
    def jenkins = [
        // same as above
    ] as CpsScript
    jenkins.currentBuild = [
        // Add attributes you need here. E.g. result:
        result:null,
    ]
    return jenkins
}

关于jenkins - 模拟 Jenkins 管道步骤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50165079/

相关文章:

java - "Too few invocations"但方法被调用并且所有内容都是使用 GroovySpy 或 GroovyMock 创建的

javascript - 如何在 Jest 中模拟嵌套响应对象参数?

windows - 无法在可执行目录或任何父目录中找到 jenkins.xml 文件

groovy - 如何将 Email-Ext groovy 脚本放置在 jenkins 文件系统上

linux - 接收带有空格和双引号的字符串时,如何在 Linux 上运行的 Jenkins 中正确解析构建参数?

ruby-on-rails - Grails 中是否提供 Rails 风格的链式查询?

Jenkins 多个构建在一个工作上

java - 如何使用Spring Data Mongodb仅检索文档的特定字段?

java - 通过 XMLRPC 访问 Atlassian Confluence 时遇到困难

rest - 使用 SSL 的 SoapUI REST 模拟服务