Burlándose de pasos personalizados en archivos vars de Jenkins.
En mi biblioteca compartida de Jenkins tengo toneladas de archivos groovy en la carpeta /vars que definen pasos personalizados. Muchos de ellos tienen varios métodos definidos y un método en un archivo puede llamar a otro en el mismo archivo.
Estoy buscando una forma de simular estos métodos locales para poder probar unitariamente cada método, especialmente aquellos que llaman a otros, sin invocarlos realmente.
Imaginemos que la estructura es así:
// vars/step.groovy
def method1() {
def someVar
result = method2(someVar)
if (result) {
echo 'ok'
}
else {
echo 'no'
}
}
def method2(value) {
if (value == 1) {
return true
}
else {
return false
}
}
Obviamente, este es un ejemplo muy simplificado. Lo que necesito es una forma de simular method2
para que pueda probar method1
con result
de true
y false
, sin invocar method2
.
He intentado el patrón de helper.registerAllowedMethod
, pero eso no parece aplicarse a los métodos locales. He intentado Mockito y Spock, pero parecen exagerados para lo que necesito y demasiado abrumadores para casos simples. También intenté definir los métodos localmente en el script de prueba con mock closures, pero no puedo encontrar el lugar correcto para hacer eso y / o la sintaxis correcta.
Espero que haya una manera de hacer algo como esto:
// test/com/myOrg/stepTest.groovy
import org.junit.*
import com.lesfurets.jenkins.unit.*
import com.lesfurets.jenkins.unit.BasePipelineTest
import static groovy.test.GroovyAssert.*
class stepTest extends BasePipelineTest {
def step
@Before
void setUp() {
super.setUp()
step = loadScript("vars/step.groovy")
}
@Test
void method1Test_true () {
helper.registerAllowedMethod('method2', [], { true })
result = step.method1()
assert 'ok' == result
}
@Test
void method1Test_false () {
helper.registerAllowedMethod('method2', [], { false })
result = step.method1()
assert 'no' == result
}
}
ACTUALIZACIÓN: una cosa que he notado recientemente es que, en la traza de pila, la función local method2
no se lista. Es como si la función local se instanciara “en línea” o de alguna manera en la que no se trata de una nueva llamada, la ejecución simplemente fluye hacia ella. No conozco el término técnico. Pero explica por qué el simulacro de method2
nunca es alcanzado: nunca se llama.
ACTUALIZACIÓN 2: Esto recibió cierta atención en el repositorio de GitHub de JPU.
davy.ai
Solución para burlar los métodos locales en la biblioteca compartida de Jenkins
Si tiene una biblioteca compartida de Jenkins con varios archivos groovy en el directorio /vars que definen pasos personalizados, y desea burlar los métodos locales para probar unitariamente cada método, esto es lo que puede hacer:
El problema
Tiene un archivo groovy /vars/step.groovy con varios métodos. Un método en el archivo puede llamar a otro en el mismo archivo. Aquí hay un ejemplo:
Quiere burlar
method2
para que pueda probarmethod1
conresult
de ambos,true
yfalse
, sin invocar realmentemethod2
.La solución
Para burlar los métodos locales en la biblioteca compartida de Jenkins:
Así es cómo puede implementarlo:
1. Defina los métodos locales en una clase estática
Extraiga todos los métodos locales a una clase estática en el mismo archivo o en un archivo separado. Por ejemplo:
Observe que se movió
method2
a una clase estáticaStepMethods
y se cambió su invocación aStepMethods.method2(someVar)
.2. Burlar la clase estática utilizando PowerMockito
Agregue la biblioteca PowerMockito a sus dependencias de prueba. Por ejemplo, en su archivo
build.gradle
:Luego, cree un archivo de prueba
vars/stepTest.groovy
:Observe que estamos burlando la clase estática
StepMethods
utilizando la biblioteca PowerMockito. Estamos burlandoStepMethods.method2 (1)
para que devuelva verdadero yStepMethods.method2 (2)
para que devuelva falso.También estamos creando dos casos de prueba, uno para cuando el resultado de
method2
es verdadero y otro para cuando el resultado es falso.3. Reemplace los métodos locales con métodos burlados utilizando MetaClass
En nuestro archivo de prueba, estamos cargando el método de la biblioteca compartida
method1()
:Antes de ejecutar nuestros casos de prueba, necesitamos reemplazar los
StepMethods.method2()
originales con los métodos burlados. Podemos hacerlo utilizando MetaClass:En nuestro método
setup()
, primero estamos burlando la clase estáticaStepMethods
. Luego, estamos reemplazandoStepMethods.method2()
con nuestros métodos burlados utilizando MetaClass. Observe que estamos definiendo el método burlado como un closure que toma un argumentovalue
y devuelve verdadero o falso.Ahora podemos ejecutar nuestros casos de prueba y utilizar el
StepMethods.method2()
burlado.