DEV Community

Discussion on: How-To: Setup a unit-testable Jenkins shared pipeline library

Collapse
 
f3rdy profile image
f3rdy

Hi Adrian,

I hope you're still reading here. I still have a problem of understanding how the steps are mocked and used in your example. I've managed to rework the testing to move to spock and get rid of all that java stuff.

Now the following. I created a ProjectVersionGetter class to encapsulate the fetching of the current version (which in turn is done by calling a gradle task in the project). For simplification and testing I return a 3.0.0.0 hardly using the following class:

class ProjectVersionGetter implements Serializable {
  private Map _configuration

  ProjectVersionGetter(Map configuration) {
    _configuration = configuration
  }

  void exec() {
    IStepExecutor steps = ServiceLocator.getContext().getStepExecutor()

    String version = steps.sh(true,"echo \"3.0.0.0\"")
    _configuration.put('projectVersion', version)
  }
}

The vars file looks like this:

def call(configuration) {
  ServiceLocator.registerDefaultContext(this)

  def projectVersionGetter = new ProjectVersionGetter(configuration)
  projectVersionGetter.exec()
}

So, I provide a configuration Map where the version should be kept. In my declarative pipeline, I've got a stage like this:

      stage("Fetch version") {
        steps {
          ex_getversion config
          script {
            currentBuild.displayName = "[${currentBuild.id} ${config.projectVersion ?: 'No version set!'}"
          }
        }
      }

My simple spock test shall verify, that the projectVersion is set to the configuration map and - for the matter of simplicity - it should be valued to "3.0.0.0".

def setup() {
    _context = mock(IContext.class)
    _steps = mock(IStepExecutor.class)
    when(_context.getStepExecutor()).thenReturn(_steps)
    ServiceLocator.registerContext(_context)
  }

  def "Version is returned in configuration"() {
    when:
    def configuration = Defaults.loadDefaults([:])

    and: "ensure mandatory keys are set"

    Defaults.getMandatoryKeys().each {
      configuration.put(it, "dummy_value")
    }

    and:
    def projectVersionGetter = new ProjectVersionGetter(configuration)
    projectVersionGetter.exec()

    then:
    // verify(_steps).sh(anyString())
    configuration.containsKey('projectVersion') // FIXME: && configuration.get('projectVersion') == '3.0.0.0'
  }

The key is set, but to null. So, the main problem I have is with the line

    String version = steps.sh(true,"echo \"3.0.0.0\"")

So, I added to IStepExecutor and the Implementation a function to cover the return of the stdout to a String, so I can retrieve the version from the "gradle call" (in future):

interface IStepExecutor {
    int sh(String command)
    String sh(boolean returnStdout, String script)
    void error(String message)
}

The implementation is

    @Override
    String sh(boolean returnStdout, String script) {
        this._steps.sh returnStatus: true, returnStdout: returnStdout, script: "${script}"
    }

Can you, or someone point me to the mistake I made?

Thanks a lot,
ferdy