如何Mock Jenkins共享库vars文件内自定义步骤的本地方法进行单元测试
Jenkins共享库同文件本地方法单元测试Mock方案
问题根因
Jenkins Pipeline Unit(JPU)的helper.registerAllowedMethod仅适用于全局DSL方法的Mock,同脚本内的本地方法调用属于Groovy类内部的直接方法调度,不会走JPU的DSL方法拦截逻辑,因此常规的注册方案无法生效,你观察到的类似「内联」的堆栈表现就是该机制导致的。
可行方案:Groovy元编程动态替换方法
直接对loadScript返回的脚本实例的元类进行修改,覆盖目标方法即可实现Mock,无需引入额外框架,也不需要修改原有共享库代码,示例如下:
// test/com/myOrg/stepTest.groovy import org.junit.* import com.lesfurets.jenkins.unit.* import com.lesfurets.jenkins.unit.BasePipelineTest import static groovy.test.GroovyAssert.* class stepTest extends BasePipelineTest { def step // 保存原方法引用,用于测试后恢复 def originalMethod2 @Before void setUp() { super.setUp() step = loadScript("vars/step.groovy") originalMethod2 = step.&method2 } @After void tearDown() { // 恢复原方法,避免测试用例之间互相影响 step.metaClass.method2 = originalMethod2 } @Test void method1Test_true () { // Mock method2,固定返回true,参数要和原方法匹配 step.metaClass.method2 = { def value -> true } step.method1() // 断言echo调用的内容 assert helper.callStack.find { it.methodName == 'echo' }?.args?.get(0) == 'ok' } @Test void method1Test_false () { // Mock method2,固定返回false step.metaClass.method2 = { def value -> false } step.method1() assert helper.callStack.find { it.methodName == 'echo' }?.args?.get(0) == 'no' } }
注意事项
- 方法签名要完全匹配:Mock的闭包参数数量、顺序要和原方法一致,否则会触发Groovy方法签名匹配失败,调用到原方法
- 如果不需要保留原方法,也可以省略@Before和@After里的保存恢复逻辑,直接在每个测试用例里覆盖目标方法即可
内容的提问来源于stack exchange,提问作者Max Cascone
相关产品推荐
相关产品推荐

