ExpediaGroup / jenkins-spock

Unit-test Jenkins pipeline code with Spock
https://javadoc.io/doc/com.homeaway.devtools.jenkins/jenkins-spock
Apache License 2.0
187 stars 76 forks source link

Help/advice with testing JTE library using openshift-client plugin #102

Open max-allan-surevine opened 3 years ago

max-allan-surevine commented 3 years ago

I'm trying to test a JTE library that is using the openshift-client plugin. (I have the dependency in my build.gradle already.) My (cut down, minimal) template looks like this :

package aa;
void call(app_env) {
  stage("A and A") {
        def build_name_selector = openshift.selector( "bc", "foo" )
        if (build_name_selector.count() > 0)
        {
            echo "foo exists!"
            build_name_selector.delete()
            echo "foo deleted"
        }
    }
}

And one of my tests like this :

package aa;
class aaTest extends JTEPipelineSpecification {
    def aa = null
    def setup() {
        aa = loadPipelineScriptForTest("aa/aa.groovy")
    }
    def "testit" () {
        setup:
            def app_env = [:]
            def mockSelector = Mock(com.openshift.jenkins.plugins.OpenShiftDSL)
            getPipelineMock("openshift.selector")( _ )  >> mockSelector
            explicitlyMockPipelineStep('count')
            getPipelineMock("count")() >> 1
            explicitlyMockPipelineStep('delete')
        when:
            aa(app_env)
        then:
            2 * getPipelineMock("echo")(_)
            1 * getPipelineMock("delete")()
    }
 }

I have another test that sets count to 0 and expects 0 echoes and deletes. They both work as expected. It has taken a lot of trial and error to get to that. But it feels wrong that I have mocked the entire count() function's result to 1. There must be a "better" way! The script under test could create a different selector later and expect a different result and I have no way of setting it. NB It is not using the builtin groovy count() & delete() functions, but versions from the openshift-client library.

IF my test is totally wrong, then please throw out whichever bits are wrong and suggest improvements!

deblaci commented 3 years ago

Hi,

I think it is ok to stub the OpenShiftDSL because it is external dependency and usually we don't like to test other class. As I experienced the Mock is a little buggy, you can use only one instance in one test. I don't know the JTEPipelineSpecification so I created an example with original JenkinsSpock. I used GroovyMock now, but I usually use GroovySpy too.

package aa

import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification
import com.openshift.jenkins.plugins.OpenShiftDSL

class aaTest extends JenkinsPipelineSpecification {
  def aa = null

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

  def "testit"() {
    setup:
    def app_env = [:]
    OpenShiftDSL mockSelector = GroovyMock(OpenShiftDSL) {
      // Assertion comes here
      1 * count() >> selectorCountResult
      expectedDeleteCalls * delete()
    }
    getPipelineMock("openshift.selector")(_) >> mockSelector

    when:
    aa(app_env)

    then:
    expectedEchoCalls * getPipelineMock("echo")(_)

    where:
    selectorCountResult || expectedDeleteCalls | expectedEchoCalls
    1                   || 1                   | 2
    0                   || 0                   | 0
  }
}