He escrito una fábrica para producir java.sql.Connection
objetos:
public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {
@Override public Connection getConnection() {
try {
return DriverManager.getConnection(...);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Me gustaría validar los parámetros pasados DriverManager.getConnection
, pero no sé cómo burlarme de un método estático. Estoy usando JUnit 4 y Mockito para mis casos de prueba. ¿Hay una buena manera de burlarse / verificar este caso de uso específico?
java
unit-testing
mocking
mockito
Naftuli Kay
fuente
fuente
static
métodos de burla , sino por accidente . Esta limitación (junto con la falta de soporte para burlarse definal
clases / métodos, unew
objetos -ed) es una consecuencia natural (pero no intencional) del enfoque empleado para implementar la burla, donde se crean dinámicamente nuevas clases que implementan / extienden el tipo que se burlará; otras bibliotecas burlonas usan otros enfoques que evitan estas limitaciones. Esto también sucedió en el mundo .NET.Respuestas:
Use PowerMockito encima de Mockito.
Código de ejemplo:
Más información:
fuente
@RunWith(PowerMockRunner.class)
y debajo de eso@PowerMockRunnerDelegate(JUnit4.class)
.La estrategia típica para esquivar métodos estáticos que no tiene forma de evitar es crear objetos envueltos y usar los objetos envolventes.
Los objetos de envoltura se convierten en fachadas a las clases estáticas reales, y no las prueba.
Un objeto contenedor podría ser algo así como
Finalmente, su clase bajo prueba puede usar este objeto singleton al, por ejemplo, tener un constructor predeterminado para uso en la vida real:
Y aquí tiene una clase que se puede probar fácilmente, porque no usa directamente una clase con métodos estáticos.
Si está utilizando CDI y puede hacer uso de la anotación @Inject, entonces es aún más fácil. Simplemente haga su Wrapper bean @ApplicationScoped, inyecte esa cosa como colaborador (ni siquiera necesita constructores desordenados para las pruebas) y continúe con la burla.
fuente
Tuve un problema similar. La respuesta aceptada no funcionó para mí, hasta que hice el cambio: de
@PrepareForTest(TheClassThatContainsStaticMethod.class)
acuerdo con la documentación de PowerMock para mockStatic .Y no tengo que usar
BDDMockito
.Mi clase:
Mi clase de prueba:
fuente
Como se mencionó anteriormente, no puede burlarse de los métodos estáticos con mockito.
Si cambiar su marco de prueba no es una opción, puede hacer lo siguiente:
Cree una interfaz para DriverManager, simule esta interfaz, inyecte a través de algún tipo de inyección de dependencia y verifique en esa simulación.
fuente
Observación: cuando llama al método estático dentro de una entidad estática, debe cambiar la clase en @PrepareForTest.
Por ejemplo:
Para el código anterior si necesita burlarse de la clase MessageDigest, use
Mientras que si tienes algo como a continuación:
entonces, deberías preparar la clase en la que reside este código.
Y luego burlarse del método:
fuente
Puedes hacerlo con un poco de refactorización:
Luego puede extender su clase
MySQLDatabaseConnectionFactory
para devolver una conexión simulada, hacer afirmaciones sobre los parámetros, etc.La clase extendida puede residir dentro del caso de prueba, si se encuentra en el mismo paquete (lo que le animo a que haga)
fuente
Para burlarse del método estático, debe usar un vistazo de Powermock en: https://github.com/powermock/powermock/wiki/MockStatic . Mockito no proporciona esta funcionalidad.
Puedes leer un buen artículo sobre mockito: http://refcardz.dzone.com/refcardz/mockito
fuente
Mockito no puede capturar métodos estáticos, pero desde Mockito 2.14.0 puede simularlo creando instancias de invocación de métodos estáticos.
Ejemplo (extraído de sus pruebas ):
Su objetivo no es admitir directamente la burla estática, sino mejorar sus API públicas para que otras bibliotecas, como Powermockito , no tengan que depender de API internas o tengan que duplicar directamente algún código de Mockito. ( fuente )
fuente
También escribí una combinación de Mockito y AspectJ: https://github.com/iirekm/varia/tree/develop/ajmock
Tu ejemplo se convierte en:
fuente
Dado que ese método es estático, ya tiene todo lo que necesita para usarlo, por lo que anula el propósito de burlarse. Burlarse de los métodos estáticos se considera una mala práctica.
Si intenta hacer eso, significa que hay algo mal con la forma en que desea realizar las pruebas.
Por supuesto, puede usar PowerMockito o cualquier otro marco capaz de hacerlo, pero intente repensar su enfoque.
Por ejemplo: intente burlarse / proporcionar los objetos, que ese método estático consume en su lugar.
fuente
Use el marco JMockit . Funcionó para mi. No tiene que escribir declaraciones para burlarse del método DBConenction.getConnection (). Solo el siguiente código es suficiente.
@Mock a continuación es el paquete mockit.Mock
fuente