如何 mock/spy Jenkins.insatance 使用 spock

How to mock/spy Jenkins.insatance using spock

我的管道中有这段代码,现在我想使用 spock 框架为其添加单元测试,问题是如何模拟或监视 Jenkins.instance 和所有链接方法。

 String deployPipeline = "Deploy/${projectID}/deploy-to-prod"
 def lastRelease = Jenkins.instance.getItemByFullName(deployPipeline).getLastSuccessfulBuild()

 String lastDeployedVersion = lastRelease.getBadgeActions().findResult {
    String text = it.getText()
    if (text != null && text.matches(/^Version\=/) != null) {
        return text.find(/\d+\.\d+\.\d+/)
    }
 }

您不必模拟 Jenkins.instance 但会调用 Run for the mock object of which you define which List<BuildBadgeAction> should be returned if its getBadgeActions()

您不想测试 Jenkins 的调用堆栈,但是您的代码对列表项做了什么,是吗?

所以,你必须做类似的事情(在 JUnit 5/Mockito 半伪代码中,我不使用 Spock,但我想你明白了):

class YourClassTest {

  @InjectMocks 
  YourClass yourClass = new YourClass();

  @Mock
  Run run;


  @Test
  testYourMethod() {

    List<BuildBadgeAction> list = new ArrayList<>();
    list.add( new ... BuildBadgeAction implementation ... );
    list.add( new ... BuildBadgeAction implementation ... );
    ... 

    when( run.getBadgeActions() ).thenReturn( list );

    assertEquals( "...", yourClass.getLastDeployedVersion() ); 

  }

}

为了 @InjectMocks 工作,你必须有 a declaration Run run; in YourClass (or a constructor YourClass(Run run) or a setter setRun(Run run))

顺便说一下,接口 BuildBadgeAction 的 none 实现有一个 getText() 方法。

我结束了这样的事情

        BuildBadgeAction badge1Mock = GroovyMock(BuildBadgeAction) {
            _.getText() >> "Version= 1.2.3"
            _.getDisplayName() >> "Version= 1.2.3"
        }

        BuildBadgeAction badge2Mock = GroovyMock(BuildBadgeAction) {
            _.getText() >> "badge-2"
            _.getDisplayName() >> "badge-2"
        }

        def runMock = GroovyMock(Run) {
            _.getBadgeActions() >> {
                return [badge1Mock, badge2Mock]
            }
        }

        Item itemMock = GroovyMock(Item) {
            _.getFullName() >> "job-1"
            _.getLastSuccessfulBuild() >> { 
                runMock
            }
        }        

        def jenkinsInstanceMock = GroovyMock(Jenkins) {
            _.getItemByFullName(_) >> { String fullName ->
            itemMock
        }

        GroovySpy(Jenkins, global: true, useObjenesis: true) {
            _.getInstance() >> jenkinsInstanceMock
        }