He escrito algunas pruebas unitarias para un método estático. El método estático toma solo un argumento. El tipo de argumento es una clase final. En términos de código:
public class Utility {
public static Optional<String> getName(Customer customer) {
// method's body.
}
}
public final class Customer {
// class definition
}
Así que para la Utilityclase I se ha creado una clase de prueba UtilityTestsen la que he escrito ensayos para este método, getName. El marco de prueba de la unidad es TestNG y la biblioteca de burla que se usa es Mockito. Entonces, una prueba típica tiene la siguiente estructura:
public class UtilityTests {
@Test
public void getNameTest() {
// Arrange
Customer customerMock = Mockito.mock(Customer.class);
Mockito.when(...).thenReturn(...);
// Act
Optional<String> name = Utility.getName(customerMock);
// Assert
Assert.assertTrue(...);
}
}
Cuál es el problema ?
Mientras que las pruebas se ejecutan con éxito localmente, dentro de IntelliJ, fallan en Jenkins (cuando inserto mi código en la rama remota, se activa una compilación y las pruebas unitarias se ejecutan al final). El mensaje de error es algo como lo siguiente:
org.mockito.exceptions.base.MockitoException: No se puede burlar / espiar clase com.packagename.Customer Mockito no se puede burlar / espiar porque: - clase final
Lo que probé?
Busqué un poco para encontrar una solución pero no la encontré. Tomo nota aquí que estoy no autorizado a cambiar el hecho de que Customeres una última clase. Además de esto, me gustaría, si es posible, no cambiar su diseño (por ejemplo, crear una interfaz, que contenga los métodos de los que quiero burlarme y afirmar que la clase Cliente implementa esa interfaz, como señaló correctamente José en su comentario). Lo que probé es la segunda opción mencionada en mockito-final . A pesar de que esto solucionó el problema, frenó algunas otras pruebas unitarias :(, que no se pueden solucionar de ninguna manera aparente.
Preguntas
Aquí están las dos preguntas que tengo:
- ¿Cómo es eso posible en primer lugar? ¿No debería fallar la prueba tanto a nivel local como en Jenkins?
- ¿Cómo se puede solucionar esto en función de las restricciones que mencioné anteriormente?
Gracias de antemano por cualquier ayuda.
fuente

enable finalconfiguración funciona en su espacio de trabajo, pero cuando se ejecutaJenkinsno puede encontrar este archivo. Verifique dóndeJenkinsestá buscando el archivo y si realmente está allí o no.CustomerTiene alguna lógica o es solo una clase de datos tontos? Si se trata solo de un conjunto de campos con captadores y establecedores, puede crear una instancia.Respuestas:
Un enfoque alternativo sería utilizar el patrón 'método para clasificar'.
Aquí hay un buen blog sobre el tema: https://simpleprogrammer.com/back-to-basics-mock-eliminating-patterns/
fuente
Obviamente es una especie de especificidad ambiental. La única pregunta es: cómo determinar la causa de la diferencia.
Le sugiero que verifique el
org.mockito.internal.util.MockUtil#typeMockabilityOfmétodo y compare, quémockMakerse usa realmente en ambos entornos y por qué.Si
mockMakeres lo mismo, compare las clases cargadasIDE-ClientvsJenkins-Client, ¿tienen alguna diferencia en el momento de la ejecución de la prueba?El siguiente código está escrito en el supuesto de OpenJDK 12 y Mockito 2.28.2, pero creo que puede ajustarlo a cualquier versión realmente utilizada.
Con una regla separada para simulacros en línea:
fuente
Asegúrese de ejecutar la prueba con los mismos argumentos. Compruebe si sus configuraciones de ejecución inteligente coinciden con las jenkins. https://www.jetbrains.com/help/idea/creating-and-editing-run-debug-configurations.html . Puede intentar ejecutar la prueba en la máquina local con los mismos argumentos que en jenkins (desde la terminal), si falla, eso significa que el problema está en los argumentos
fuente
org.mockito.plugins.MockMakertambién existe en la máquina jenkins. Yo uso la misma JVM en máquinas bot. Comprobaré los 3 que señaló. Gracias