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 Utility
clase I se ha creado una clase de prueba UtilityTests
en 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 Customer
es 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 final
configuración funciona en su espacio de trabajo, pero cuando se ejecutaJenkins
no puede encontrar este archivo. Verifique dóndeJenkins
está buscando el archivo y si realmente está allí o no.Customer
Tiene 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#typeMockabilityOf
método y compare, quémockMaker
se usa realmente en ambos entornos y por qué.Si
mockMaker
es lo mismo, compare las clases cargadasIDE-Client
vsJenkins-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.MockMaker
también existe en la máquina jenkins. Yo uso la misma JVM en máquinas bot. Comprobaré los 3 que señaló. Gracias