简体   繁体   English

使用Groovy进行Jenkins管道模拟

[英]Jenkins pipeline mocking with Groovy

I'm quite new to the Jenkins pipeline stuff and I am building a small shared library in Groovy. 我对Jenkins管道技术还很陌生,并且正在Groovy中构建一个小型共享库。
In this context I am trying to come up with some unit tests, and then I have to mock the pipeline object. 在这种情况下,我试图提出一些单元测试,然后我必须模拟管道对象。

Basically I am having a Groovy class containing a method that does some stuff with credentials: 基本上,我有一个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}'"
    }
  }
}

So when it comes to unit testing this method I have created a PipelineMock Groovy class to (try to) mock the withCredentials and usernamePassword . 因此,当涉及到对该方法进行单元测试时,我创建了PipelineMock Groovy类来(模拟) withCredentialsusernamePassword

The test class is like this (a bit simplified): 测试类是这样的(有点简化):

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'))
  }

}

And the PipelineMock I came up with is: 我想出的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()
  }

}

Initially I was just calling the closure() so to execute the code, but I got the error groovy.lang.MissingPropertyException: No such property: MY_USER for class: MyClass when the execution reaches the pipeline.sh line. 最初,我只是调用closure()来执行代码,但是当执行到达pipeline.sh行时,出现错误groovy.lang.MissingPropertyException: No such property: MY_USER for class: MyClass
So I tried to inject test values into MY_USER and MY_PASSWORD so they can be resolved with the for loop. 因此,我尝试将测试值注入MY_USERMY_PASSWORD以便可以使用for循环对其进行解析。 I got the exact same error but this time when calling the closure.setProperty . 我遇到了完全相同的错误,但这一次是在调用closure.setProperty I checked at debug time and the arg.get('usernameVariable') resolves correctly to MY_USER . 我在调试时检查了arg.get('usernameVariable')正确解析为MY_USER

So well, I'm lost. 好吧,我迷路了。 I'm not really a Groovy expert, so I probably miss something. 我并不是真正的Groovy专家,所以我可能会错过一些东西。 Any help on understanding what's happening would be appreciated! 任何了解正在发生的事情的帮助将不胜感激!

This does look like an ideal candidate for using JenkinsPipelineUnit as @mkobit mentioned in a comment, but for the sake of academic interest, the sample in the question would in fact work with minor changes related to delegator. 这看起来确实是使用JenkinsPipelineUnit作为注释中提到的@mkobit的理想候选人,但是出于学术兴趣,问题中的示例实际上将在与委托人相关的微小变化下工作。 There is also a typo in the original MyClass.my method which I believe should have been MyClass.call . 原始MyClass.my method还存在一个错字,我认为应该是MyClass.call Here is the working PipelineMock 这是工作中的PipelineMock

class PipelineMock {

  String commandCalled

  def sh(String command) {
    commandCalled = command
  }

  def usernamePassword(Map inputs) {
    inputs
  }

  def withCredentials(List args, Closure closure) {
    def delegate = [:]
    for (arg in args) {
        delegate[arg.get('usernameVariable')] = 'the_login'
        delegate[arg.get('passwordVariable')] = 'the_password'
    }
    closure.delegate = delegate
    closure()
  }

}

And here is the MyClass without the typo: 这是没有错字的MyClass

class MyClass implements Serializable {

  def pipeline

  MyClass(def pipeline) {
    this.pipeline = pipeline
  }

  void call(String version) {
    pipeline.withCredentials([pipeline.usernamePassword(credentialsId: 'MY_ID', usernameVariable: 'MY_USER', passwordVariable: 'MY_PASSWORD')]) {
        pipeline.sh "echo ./release.sh complete --username ${MY_USER} --password ${MY_PASSWORD} --version '${version}'"
    }
  }
}

The test should work as is. 该测试应该可以正常工作。

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

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