如何 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
}
我的管道中有这段代码,现在我想使用 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
}