2012-05-31 13 views
24

¿Es posible interceptar todas las invocaciones de métodos en un simulacro de forma genérica?Mockito: interceptar cualquier invocación de método en un simulacro

Ejemplo

Dada una clase proporcionada proveedor como:

public class VendorObject { 

    public int someIntMethod() { 
     // ... 
    } 

    public String someStringMethod() { 
     // ... 
    } 

} 

Me gustaría crear una maqueta que re-dirige todo método llama a otra clase donde no son coincidentes método firmas:

public class RedirectedToObject { 

    public int someIntMethod() { 
     // Accepts re-direct 
    } 

} 

La construcción when(). thenAnswer() t en Mockito parece ajustarse a la factura, pero no puedo encontrar una manera de hacer coincidir cualquier llamada al método con cualquier argumento. La InvocationOnMock ciertamente me da todos estos detalles de todos modos. ¿Hay una manera genérica de hacer esto? Algo que podría tener este aspecto, en el que cuando se reemplaza con código apropiado (vo *.):

VendorObject vo = mock(VendorObject.class); 
when(vo.anyMethod(anyArgs)).thenAnswer(
    new Answer() { 
     @Override 
     public Object answer(InvocationOnMock invocation) { 

      // 1. Check if method exists on RedirectToObject. 
      // 2a. If it does, call the method with the args and return the result. 
      // 2b. If it does not, throw an exception to fail the unit test. 

     } 
    } 
); 

Adición de envolturas alrededor de las clases de proveedor para hacer burla fácil no es una opción porque:

  1. Demasiado grande una base de código existente.
  2. Parte de aplicaciones extremadamente críticas para el rendimiento.
+0

No me digas que es tan simple como cuando (vo) .thenAnswer (...): O – Karle

+0

"Parte de las aplicaciones extremadamente críticas para el rendimiento". ¿Cómo se puede agregar un objeto simulado/proxy diferente de agregar un contenedor en este caso? ¿Estás interesado en hacer esto solo para pruebas unitarias o en la aplicación real? –

+0

@mattb: el aspecto de rendimiento no es el mejor argumento contra el uso de clases contenedoras. Creamos una interfaz basada en el objeto del proveedor original y una clase de implementación que reenvía las solicitudes al objeto real del proveedor. El tiempo de ejecución para esto va a ser pequeño en comparación con el objeto real del proveedor que hace su trabajo. El argumento más importante es la base de código existente que usa los objetos del proveedor directamente. – Karle

Respuesta

39

Creo que lo que desea es:

VendorObject vo = mock(VendorObject.class, new Answer() { 
    @Override 
    public Object answer(InvocationOnMock invocation) { 

     // 1. Check if method exists on RedirectToObject. 
     // 2a. If it does, call the method with the args and return the 
     // result. 
     // 2b. If it does not, throw an exception to fail the unit test. 

    } 
}); 

Por supuesto, si desea utilizar este método con frecuencia, no hay necesidad de que la respuesta sea anónimo.

Desde el documentation: "Es una característica bastante avanzada y normalmente no la necesita para escribir pruebas decentes. Sin embargo, puede ser útil cuando se trabaja con sistemas heredados". Suena como tu.

Cuestiones relacionadas