【发布时间】:2018-08-20 07:58:22
【问题描述】:
我对 Jenkins 管道的东西还很陌生,我正在 Groovy 中构建一个小型共享库。
在这种情况下,我试图提出一些单元测试,然后我必须模拟管道对象。
基本上,我有一个 Groovy 类,其中包含一个使用凭据执行某些操作的方法:
class MyClass implements Serializable {
def pipeline
MyClass(def pipeline) {
this.pipeline = pipeline
}
void my method(String version) {
pipeline.withCredentials([pipeline.usernamePassword(credentialsId: 'MY_ID', usernameVariable: 'MY_USER', passwordVariable: 'MY_PASSWORD')]) {
pipeline.sh "./release.sh complete --username ${MY_USER} --password ${MY_PASSWORD} --version '${version}'"
}
}
}
因此,在对这个方法进行单元测试时,我创建了一个 PipelineMock Groovy 类来(尝试)模拟 withCredentials 和 usernamePassword。
测试类是这样的(有点简化):
class MyClassTest {
@Test
void callWithWithVersionShouldCallCommad() {
def pipelineMock = new PipelineMock()
def myClass = new MyClass(pipelineMock)
myClass('1.0.1')
assertTrue(pipelineMock.commandCalled.startsWith('./release.sh complete'))
}
}
而我想出的 PipelineMock 是:
class PipelineMock {
String commandCalled
def sh(String command) {
commandCalled = command
}
def usernamePassword(Map inputs) {
inputs
}
def withCredentials(List args, Closure closure) {
for (arg in args) {
closure.setProperty(arg.get('usernameVariable'), 'the_login')
closure.setProperty(arg.get('passwordVariable'), 'the_password')
}
closure()
}
}
最初我只是调用closure() 来执行代码,但是当执行到达pipeline.sh 行时,我得到了错误groovy.lang.MissingPropertyException: No such property: MY_USER for class: MyClass。
所以我尝试将测试值注入MY_USER 和MY_PASSWORD,以便可以使用for 循环解决它们。我得到了完全相同的错误,但这次调用closure.setProperty 时。我在调试时进行了检查,arg.get('usernameVariable') 正确解析为MY_USER。
好吧,我迷路了。我不是真正的 Groovy 专家,所以我可能会错过一些东西。任何有关了解正在发生的事情的帮助将不胜感激!
【问题讨论】:
-
Jenkins 对 Groovy 进行了一些低级编译器和运行时更改,并且很难模拟这些。我建议查看 JenkinsPipelineUnit 和可能的 this Gradle plugin(注意:我是插件的作者)看看这些对你有没有帮助。
-
@mkobit 是的,JenkinsPipelineUnit 应该是正确的答案,但是 OP 代码不起作用的原因并不是因为 Jenkins 运行时。我相信 OP 正试图将其作为没有 Jenkins 运行时的常规 Groovy 单元测试运行。
标签: unit-testing jenkins groovy closures jenkins-pipeline