2012-01-25 12 views
8

Estoy intentando burlarme de algunos métodos basados ​​en la reflexión. A continuación puede ver los detalles,Llamadas basadas en Reflexión burlona

clase bajo prueba

public class TracerLog { 
    @AroundInvoke 
    public Object logCall(InvocationContext context) throws Exception { 
     Logger logger = new Logger(); 
     String message = "INFO: Invoking method - " 
       + context.getMethod().getName() + "() of Class - " 
       + context.getMethod().getDeclaringClass(); 

     logger.write(message); 
     return context.proceed(); 
    } 
} 

prueba

public class TracerLogTest { 

@Mock 
InvocationContext mockContext; 
@Mock 
Logger mockLogger; 
@InjectMocks 
private TracerLog cut = new TracerLog(); 

@BeforeMethod 
public void setup() { 
    MockitoAnnotations.initMocks(this); 
} 

@Test 
public void logCallTest() throws Exception { 
    when(mockContext.proceed()).thenReturn(true); 
    when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass"); 
    cut.logCall(mockContext); 
    verify(mockContext).proceed(); 
} 

}

o

@Test 
public void logCallTest() throws Exception { 
    when(mockContext.proceed()).thenReturn(true); 
    when(mockContext.getMethod().getName()).thenReturn("someMethod"); 
    when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass"); 
    cut.logCall(mockContext); 
    verify(mockLogger).write(anyString()); 
    verify(mockContext).proceed(); 
} 

embargo, las pruebas fallan con una NullPointerException . Entiendo que estoy haciendo algo mal contra los conceptos de burla, pero no entiendo de qué se trata. ¿Podría por favor arrojar algo de luz sobre él y también sugerirme cómo se puede probar este método?

Gracias.

+0

¿Cómo está creando sus objetos simulados y su objeto bajo prueba? ¿Puedes publicar toda tu clase de prueba, en lugar de solo el método de prueba? Gracias. –

+0

@DavidWallace He editado la pregunta para incluir el código completo. – Bala

Respuesta

17

Necesita un objeto Método y un objeto Clase. Según su comentario, Mockito no puede burlarse de un Método, por lo que necesitará uno real. No he probado esto, pero creo que esto funcionaría. En lugar de:

when(mockContext.getMethod().getName()).thenReturn("someMethod"); 
when(mockContext.getMethod().getDeclaringClass().getName()).thenReturn("someClass"); 

Es necesario:

// any method will do, but here is an example of how to get one. 
Method testMethod = this.getClass().getMethod("logCallTest"); 

when(mockContext.getMethod()).thenReturn(testMethod); 

Obviamente, getName() no volverá "algunMetodo" más y getDeclaringClass().getName() devolverá el nombre de esta clase de prueba (en el ejemplo), pero aunque no podías 'Elija lo que devuelve, lo que devuelve es aún determinista, por lo que debe poder verificar todo lo que necesite. (Por supuesto, si usted necesita para espiar o Verificar que una llamada fue hecha en el propio método objeto, todavía está atascado.)

+0

Gracias por su respuesta, pero Mockito se queja de que no puede burlarse o espiar java.lang.reflect.Method. ¿Hay alguna otra forma de lograr esto? – Bala

+0

He editado mi respuesta para mostrar cómo usar un objeto de método real. Esto debería abordar los ejemplos simples en su pregunta, pero todavía hay limitaciones. – jhericks

+0

Gracias por su sugerencia, pero mockContext.getMethod(). GetDeclaringClass() no funcionará en este caso. – Bala

3

Sí, el problema es que mockContext.getMethod() va a devolver null. Entonces, cada vez que ejecutas esto, luego llamas algo al resultado (getDeclaringClass() o getName()) obtendrás el NPE. Probablemente desee utilizar la respuesta predeterminada RETURNS_DEEP_STUBS, cuando configure el simulacro. Algo así como

@Mock(answer = RETURNS_DEEP_STUBS) private InvocationContext mockContext; 

debería hacer el truco.

+0

Hola David, casi siempre estoy de acuerdo contigo. Pero para el lector: el Método es una clase final, no se puede burlar con Mockito;) Tampoco recomendaría que se burlen de tipos que no son de su propiedad. – Brice

+0

Oh molesta. Brice tiene razón (por lo general lo es, sobre estas cosas). Dado que Mockito no puede burlarse de las clases finales, no veo una manera de hacer lo que quería el cartel original. Lo siento. –

+0

@Brice Bueno, estoy de acuerdo contigo, pero InvocationContext no es una clase final y tiene que ser burlado en mi caso porque, no quiero que el servidor de aplicaciones se ejecute para mi prueba. ¿Me equivoqué en algún lado? – Bala

Cuestiones relacionadas