代码之家  ›  专栏  ›  技术社区  ›  Xendar

Jenkins管道模拟Groovy

  •  3
  • Xendar  · 技术社区  · 6 年前

    我对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() 所以要执行代码,但我得到了错误 groovy.lang.MissingPropertyException: No such property: MY_USER for class: MyClass 当执行达到 pipeline.sh 线
    所以我尝试将测试值注入 MY_USER MY_PASSWORD 所以可以通过 for 环我得到了完全相同的错误,但这次在调用 closure.setProperty 。我在调试时进行了检查 arg.get('usernameVariable') 正确解析为 MY\u用户

    好吧,我迷路了。我不是一个真正的优秀专家,所以我可能错过了一些东西。如果您能帮助我们了解正在发生的事情,我们将不胜感激!

    1 回复  |  直到 6 年前
        1
  •  4
  •   haridsv    6 年前

    这看起来确实是使用 JenkinsPipelineUnit 正如@mkobit在一篇评论中提到的,但出于学术兴趣的考虑,问题中的示例实际上可以与委托人相关的微小更改一起使用。原文中也有一个拼写错误 MyClass.my method 我认为应该是 MyClass.call 。这是工作 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()
      }
    
    }
    

    这是 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}'"
        }
      }
    }
    

    测试应按原样进行。