JenkinsPipelineUnit
JenkinsPipelineUnit copied to clipboard
Mock imported classes
How can I mock imported classes (specifically the constructor) when using JPU?
Example:
vars/someCommand.groovy
:
import com.mycompany.jenkins.SomeClass
def call(Map args = [:]) {
def someArg = args.get('someArg')
SomeClass someInstance = new SomeClass(someArg)
...
}
test/vars/SomeCommandTest.groovy
:
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.Before
import org.junit.Test
class SomeCommandTest extends BasePipelineTest {
def someCommand
@Before
void setUp() {
super.setUp()
someCommand = loadScript("vars/someCommand.groovy")
}
@Test
void "should do some test"() {
binding.setVariable('env', [
...
])
//TODO: How to mock new SomeClass(someArg)
}
}
I'm not sure why you'd want to mock the class you are planning on testing, but maybe your pseudo-code above is missing something which would explain this.
Anyways, for the case that you describe, you can simply write standard unit tests for SomeClass
and test the constructor by normal means:
package import com.mycompany.jenkins
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.Before
import org.junit.Test
class SomeClassTest extends BasePipelineTest {
def script
@Before
void setUp() {
super.setUp()
this.script = loadScript('test/resources/EmptyPipeline.groovy')
}
@Test
void testConstruction() {
SomeClass someClass = new SomeClass(someArg: 'foo')
// assert that someClass was instantiated correctly...
}
}
In the above example, an "empty" pipeline is loaded just to get a script context, which is typically passed to the classes during construction so they can run pipeline steps. That pipeline actually looks like this:
void execute() {
node {
stage('Empty') {}
}
}
return this
If your class doesn't need to run pipeline steps, than you can skip this part. We don't bother testing the singletons (that is, vars/*.groovy
files) because they are typically meant to be simple one-liners, and all the actual work is done in the classes.
You can see a working example of this in an open-source pipeline library published by my company.
Does this answer your question?
@msabastian
You can try to use groovy.mock.interceptor.MockFor
see https://www.groovy-lang.org/testing.html#_mocking_and_stubbing
//Jenkinsfile
def job_cfg = new URL("https://jenkins.example.com/job/test/api?json").getText()
echo job_cfg
//TestCase
import groovy.mock.interceptor.MockFor
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.Before
import org.junit.Test
class TestExample extends BasePipelineTest {
@Before void setUp() throws Exception {
super.setUp()
}
@Test should_execute_without_errors() throws Exception {
def mockURLContext = new MockFor(URL.class)
mockURLContext.demand.getText { getClass().getResource('JobApiStub.json').text }
mockURLContext.use {
def script = runScript("Jenkinsfile")
}
printCallStack()
assertJobStatusSuccess()
}
}
See also #141.
@msabastian were you able to solve above problem with MockFor()
? I have the same issue.