Reputation: 19903
I have this code in my pipeline, now I want to add unit test for it using spock
framework, the issue is how to mock or spy Jenkins.instance
and all chaining methods.
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+/)
}
}
Upvotes: 0
Views: 584
Reputation: 19903
I ended up something like this
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
}
Upvotes: 1
Reputation: 14772
You don't have to mock Jenkins.instance
but Run
for the mock object of which you define which List<BuildBadgeAction>
should be returned if its getBadgeActions()
is called.
You don't want to test Jenkins' call stack but what your code does with items of a list, do you?
So, you have to do something like (in JUnit 5/Mockito semi-pseudocode, I don't use Spock, but I think you get the idea):
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() );
}
}
For @InjectMocks
to work you have to have a declaration Run run;
in YourClass
(or a constructor YourClass(Run run)
or a setter setRun(Run run)
).
And, BTW, none of the implementations of the interface BuildBadgeAction
has a getText()
method.
Upvotes: 0