java - Mockito bypass método estático para la prueba
mockito spy (3)
Cambié mi prueba a:
@Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
doReturn(pdo ).when( handler2 ).getIPDO();
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
Resuelto después de leer Effective Mockito .
Necesito probar el método handleIn () usando Mockito.
Sin embargo, el código debe llamar a este código heredado Util.getContextPDO que es un método estático.
Tenga en cuenta que en el entorno de prueba, este Util.getContextPDO siempre devuelve Exception, y tengo la intención de omitir este Util.getContextPDO () siempre devuelve un IPDO ficticio.
public class MyClass {
public IPDO getIPDO()
{
return Util.getContextPDO(); // note that Util.getContextPDO() is a static, not mockable.
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
// some important business logic.
return result;
}
}
Inicialmente pensé que esto se podía lograr utilizando spy () de la clase "MyClass", por lo que puedo simular el valor de retorno de getIPDO (). Debajo está mi esfuerzo inicial usando espía ()
@Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
when(handler2.getIPDO()).thenReturn(pdo);
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
Sin embargo, el cuándo (handler2.getIPDO ()). ThenReturn (pdo); está lanzando la excepción que quiero evitar (porque handler2.getIPDO ()) parece llamar al método real.
¿Alguna idea sobre cómo probar esta parte del código?
Una buena técnica para deshacerse de llamadas estáticas en API de terceros es ocultar la llamada estática detrás de una interfaz.
Digamos que haces esta interfaz:
interface IPDOFacade {
IPDO getContextPDO();
}
y tiene una implementación predeterminada que simplemente llama al método estático en la API de terceros:
class IPDOFacadeImpl implements IPDOFacade {
@Override
public IPDO getContextPDO() {
return Util.getContextPDO();
}
}
Entonces, simplemente se trata de inyectar una dependencia de la interfaz en MyClass
y usar la interfaz, en lugar de la API de terceros directamente:
public class MyClass {
private final IPDOFacade ipdoFacade;
public MyClass(IPDOFacade ipdoFacade) {
this.ipdoFacade = ipdoFacade;
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
someImportantBusinessLogic(pdo);
return result;
}
...
}
En la prueba de su unidad, puede burlarse fácilmente de su propia interfaz, colóquela de la manera que desee e inyéctela en la unidad bajo prueba.
Esta
- evita la necesidad de hacer privado el paquete privado de métodos.
- hace que tus pruebas sean más legibles evitando la burla parcial.
- aplica inversión de control.
- desacopla su aplicación de una biblioteca de terceros específica.
when(handler2.getIPDO()).thenReturn(pdo);
Llamará al método y luego devolverá el pdo
independientemente.
Mientras:
doReturn(pdo).when(handler2).getIPDO();
Devolverá pdo sin llamar al método getIPDO()
.