I have Groovy PSL project and I would like to add tests for code that calls outside classes.
So, for example, I would like to mock this DeploymentMetrics
class and it's methods so it doesn't call real class. All I want is to verify it was called.
CICDTest.groovy
import com.lesfurets.jenkins.unit.BaseRegressionTest
import org.junit.Before
import org.junit.Test
class CICDTest extends BaseRegressionTest {
def serviceVersion = "12345rds234"
String team = "TEAM"
String service = "SERVICE"
String deployEnv = "Development"
String deployType = "App Code Deployment"
String deployReason = "Routing Change"
@Override
@Before
void setUp() throws Exception {
super.setUp()
callStackPath = "test/vars/callstacks/"
binding.setProperty('steps', 'some')
binding.setVariable('env', [getEnvironment: {[:]}])
}
@Test
void publishCdMetricsSuccess() throws Exception {
cicd = loadScript('vars/cicd.groovy')
cicd.publishCdMetrics(serviceVersion, team, service, deployEnv, deployType, deployReason)
printCallStack()
}
}
/vars/cicd.groovy
import spg.dora.cd.DeploymentMetrics
def publishCdMetrics(serviceVersion, String team, String service, String deployEnv, String deployType, String deployReason) {
try {
String[] deployRegions = ['us-west-2'] as String[]
DeploymentMetrics metricsHandler = new DeploymentMetrics(steps, env, docker)
metricsHandler.postMetric(team, service, serviceVersion, deployEnv, deployType, deployReason, deployRegions)
} catch (Exception exception) {
error "Failed to publish CD metrics: ${exception}"
}
}
DeploymentMetrics.groovy <- not owned by me (cannot modify)
class DeploymentMetrics implements Serializable {
DeploymentMetrics(steps, env, docker) {
this.steps = steps
this.env = env
this.common_shell = new CommonShell(steps, env)
}
def postMetric(String team, String service, String serviceVersion, String environment, String category, String reason, String[] awsRegions) {
...
//doesn't return anything
}
}
I tried new MockFor()
following this example:
def mockDeploymentMetrics = new MockFor(DeploymentMetrics, true)
mockDeploymentMetrics.demand.with {
DeploymentMetrics(any(), any(), any()) {
new DeploymentMetrics(null, null, null)
}
postMetric { }
}
mockDeploymentMetrics.use {
cicd = loadScript('vars/cicd.groovy')
cicd.publishCdMetrics(serviceVersion, team, service, deployEnv, deployType, deployReason)
}
I tried different combinations of Mock
and then PowerMock
@PrepareForTest(DeploymentMetrics.class)
class CICDTest extends BaseRegressionTest {
@Override
@Before
void setUp() throws Exception {
super.setUp()
//deploymentMetrics = mock(DeploymentMetrics.class)
deploymentMetrics = PowerMockito.mock(DeploymentMetrics.class)
when(deploymentMetrics.postMetric(any(), any(), any(), any(), any(),any(), any())).thenReturn(new Object())
}
}
I tried metaClass.constructor
DeploymentMetrics.metaClass.constructor = { steps, env, docker ->
def constructor = DeploymentMetrics.class.getConstructor(Object.class,Object.class,Object.class)
def instance = constructor.newInstance(any(), any(), any())
I tried instantiating class and spying on that object following this example:
DeploymentMetrics deploymentMetrics = new DeploymentMetrics(binding.getVariable("steps"), binding.getVariable("env"), binding.getVariable("docker"))
deploymentMetricsSpy = spy(deploymentMetrics)
doReturn(new Object()).when(deploymentMetricsMock).postMetric(anyString(), anyString(), anyString(), anyString(), anyString(), anyString(), any())
But it is always going inside real class and it's method. I actually do not want it to ever go inside real constructor, cause it calls other classes' constructors and it fails. So I want to avoid doing new on it completely.
Note: DeploymentMetrics
only has 1 constructor that takes 3 Object parameters
I followed many examples out there, but nothing worked.
Can someone shed some light?
question from:
https://stackoverflow.com/questions/65946672/groovy-how-to-mock-imported-class-and-its-methods