unit-testing - test - tipos de pruebas unitarias
Método de contaje de invocaciones en pruebas unitarias (7)
¿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?
Dado un ejemplo de clase "RoleRepository" con un único método "getRole (String user)" que devolvería un rol.
Asumiendo que ha declarado este objeto como Mock o Spy y quiere verificar si se llama al método getRole (String) una vez.
Haría 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";
}
}
}
Dependiendo de los métodos que desee contar, puede crear una configuración de prueba, con un asesoramiento @Before
coincida 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 usar AspectJ de vanJ o Spring AOP a través de las configuraciones anteriores o XML si lo encuentra más fácil.
Puede crear diferentes puntos de corte / aspecto si es necesario.
En Mockito puedes 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();
Parece que es posible que desee un espía de prueba . Ver, por ejemplo, Mockito.spy() .
Parece que es posible que desee utilizar los métodos .expects (1) que suelen proporcionar los frameworks de prueba.
Usando mockito, si estaba probando una Lista y quería verificar que se llamara a clear 3 veces y se llamara al menos una vez con estos parámetros, haga lo siguiente:
List mock = mock(List.class);
someCodeThatInteractsWithMock();
verify(mock, times(3)).clear();
verify(mock, atLeastOnce()).add(anyObject());
(Desde http://code.google.com/p/mockito/wiki/MockitoVSEasyMock )
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);
Tienes algunas opciones
1) Agregue un código especial que cuente las 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) Use 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 solución mejor sería verificar que el resultado sea el esperado, en lugar de verificar cómo funciona internamente.