2011-10-08 11 views
31

¿Cuál es la mejor manera de contar las invocaciones de métodos en una Prueba Unitaria? ¿Alguno de los marcos de prueba lo permiten?Invocaciones del método de conteo en Pruebas unitarias

+0

Podría explicar lo que está tratando de hacer? ¿Estás tratando de medir la cobertura del código? ¿Actuación? ¿Eficiencia? –

+0

No realmente. Solo quiero comprobar que cuando llamo al método de prueba testXXX(), se llama al método foo() en una clase al menos N veces. – user855

+0

¿Esto no es posible? Sé que los marcos de Mocking me permiten afirmar en los recuentos de invocación en los objetos de Mock.¿No es posible hacerlo en objetos reales? – user855

Respuesta

1

usted tiene un par de opciones

1) Añadir un código especial que cuenta invocaciones en la función. Funcionará, pero no es una gran solución.

2) Después de ejecutar las pruebas de su unidad, verifique la cobertura del código. La mayoría de las herramientas de cobertura contarán las invocaciones, pero están realmente diseñadas para el procesamiento posterior.

3) Utilice un perfilador. Un generador de perfiles le permitirá contar cuántas veces se invoca una función. Este es un proceso muy manual, por lo que no está diseñado para pruebas unitarias.

Una mejor solución sería comprobar que la salida es lo que espera en lugar de comprobar cómo funciona internamente.

3

Dependiendo de cuáles son los métodos que desea contar, puede crear una configuración de prueba, con un consejo @Before que coincidan con su clase/paquete/método:

import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.annotation.Pointcut; 

@Aspect 
public class MethodCounterAspect { 

    private int counter = 0 // or inject the Counter object into this aspect 

    @Pointcut("execution(* com.sample.your.package.*.*(..))") 
    public void methodsToCount() {} 

    @Before("methodsToCount()") 
    public void execute() throws Throwable { 
     counter++; // or update the counter injected into this aspect.. 
    } 

    // get the counter 
} 

Puede utilizar la vainilla AspectJ o primavera AOP a través encima o Configuraciones XML si lo encuentras más fácil.

Puede crear diferentes puntos de corte/aspecto si es necesario.

+0

Si solo quiere ver el número de invocaciones, esta es la manera de hacerlo. Si desea verificar las invocaciones, los marcos falsos generalmente envuelven este patrón con aserciones. Ver mi respuesta para la versión simulada. –

+0

la pregunta es "_¿Cuál es la mejor manera de contar las invocaciones de métodos en una Prueba de unidad_". Lo anterior le permitirá hacer simplemente eso => ​​** contabilizar invocaciones de método en pruebas de Unidad/Integración ** sin contaminar las pruebas. – tolitius

+0

Estoy de acuerdo, razón por la cual te voté. Pero en los comentarios, el autor pregunta sobre la afirmación de los recuentos de invocación de objetos reales frente a objetos simulados. Si realmente quiere probar las invocaciones, debería usar una biblioteca simulada porque para eso están diseñadas. –

40

Parece que es posible que desee utilizar los métodos .expects (1) que suelen proporcionar los frameworks de prueba.

Usando Mockito, si estuviera probando una lista y quería comprobar que claro se llama 3 veces y añada fue llamado al menos una vez con estos parámetros hace lo siguiente:

List mock = mock(List.class);   

someCodeThatInteractsWithMock();     

verify(mock, times(3)).clear(); 
verify(mock, atLeastOnce()).add(anyObject());  

(De http://code.google.com/p/mockito/wiki/MockitoVSEasyMock)

6

Puede contar el número de invocación de método utilizando la interfaz Respuesta en Mockito.

ConnectionPool mockedConnectionPool = mock(ConnectionPool.class); 

    final int[] counter = new int[1]; 

    when(mockedConnectionPool.getConnection()).then(new Answer<Connection>() { 

     @Override 
     public Connection answer(InvocationOnMock invocation) throws Throwable { 
      counter[0]++; 
      return conn; 
     } 

    }); 
    // some your code 

    assertTrue(counter[0] == 1); 
7

En Mockito se puede hacer algo como esto:

YourService serviceMock = Mockito.mock(YourService.class); 

// code using YourService 

// details of all invocations including methods and arguments 
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations(); 
// just a number of calls of any mock's methods 
int numberOfCalls = invocations.size(); 
+0

Encontré que este es el método más simple y efectivo para usar, donde tiene acceso al objeto burlado. – iZian

+0

Gracias Jakub, también es bueno porque si inspecciona el objeto puede ver dónde y qué funciones se están llamando. – Stoffe

2

Dado un "RoleRepository" ejemplo de la clase con un único método "getRole (usuario String)", que devolvería un papel.

Suponiendo que ha declarado este objeto como Mock o Spy y desea comprobar si se llama al método getRole (String) una vez.

Se podría hacer algo como: Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString());

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 
import org.mockito.Spy; 
import org.mockito.junit.MockitoJUnitRunner; 

@RunWith(MockitoJUnitRunner.class) 
public class RoleRepositoryTest { 

    @Spy 
    private RoleRepository roleRepository = new RoleRepository(); 

    @Test 
    public void test() { 
     roleRepository.getRole("toto"); 
     Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString()); 
    } 

    public static class RoleRepository { 

     public String getRole(String user) { 
      return "MyRole"; 
     } 
    } 
}