ExpediaGroup/jenkins-spock

shared lib - unable to test invocations of a function from another var script

Closed this issue · 2 comments

Hi @awittha. This might not be an actual bug but I cannot seem to find a way to do this.

I have a shared library with 2 scripts in the vars folder called archive.groovy and fs.groovy. Both scripts end with the return this. Here is a short snapshot of the content of fs.groovy:

void copyFiles(pattern, destination) {
    fileOperations([
        fileCopyOperations(includes: pattern, excludes: "*.log", targetLocation: destination, flattenFiles: false)
    ])
}

return this

Here is a short snapshot of the content of archive.groovy:

void call(src) {
    fs.copyFiles(src, "/opt/archival_dir")
}

return this

In my pom.xml file, I've added the plugin providing the fileCopyOperations step

<dependency>
    <groupId>sp.sd</groupId>
    <artifactId>file-operations</artifactId>
    <version>1.11</version>
    <scope>test</scope>
</dependency>

My test looks like following:

class ArchiveSpec extends JenkinsPipelineSpecification {

    def archive = null

    def setup() {
        archive = loadPipelineScriptForTest("/vars/archive.groovy")
    }

    def "calling archive copies the files to the right location"() {
        setup:
        String sourceFiles = ["a", "b", "c"].join(",")

        when:
        archive.call(sourceFiles)

        then:
        1* getPipelineMock("fileCopyOperation.call")(_) >> {
                it.includes == sourceFiles
                it.excludes == "*.log"
                it.targetLocation == "/opt/archival_dir"
        }
    }
}

However, the above results in an error as following:

org.spockframework.mock.TooFewInvocationsError: 
Too few invocations for:

1* getPipelineMock("fileCopyOperation.call")(_) >> {
            it.includes == sourceFiles
            it.excludes == "*.log"
            it.targetLocation == "/opt/archival_dir"
        }   (0 invocations)

The matched invocation is as following:
Mock for type 'Closure' named '(implicit-runtime) getPipelineMock("fs.copyFiles")'

So seems that I am not able to test the content of fs.copyFiles from within archive.call.

On the other hand, when I try to test the fs.copyFiles function call directly, I am able to get the fileCopyOperation steps like following:

class FsSpec extends JenkinsPipelineSpecification {

    def fs= null

    def setup() {
        fs = loadPipelineScriptForTest("/vars/fs.groovy")
    }

    def "call fs.copyFiles uses right args"() {
        setup:
        String sourceFiles = ["a", "b", "c"].join(",")
        String dst = "destination"

        when:
        fs.copyFiles(sourceFiles, dst)

        then:
        1* getPipelineMock("fileCopyOperation.call")(_) >> {
                it.includes == sourceFiles
                it.targetLocation == dst
        }
    }
}

I suppose I should be doing some explicitlyMockPipelineVariable("fs") but can't seem to make it work. I also tried loading the fs.groovy files just like I did with the archive = loadPipelineScriptForTest("/vars/archive.groovy") in the setup function of the ArchiveSpec but that also did not fix it.

Is it possible to test such a scenario with jenkins-spock? Thanks.

@awittha have you had a chance to look at this issue? Thanks.

Ended up using the JenkinsPipelineUnit.