Diferencia entre revisiones de «Tests De JUnit Multihilo»
(→Una solución: GroboUtils) |
(→Test multihilo - escenario: Todos los hilso ejecutan ok) |
||
Línea 44: | Línea 44: | ||
<code java> | <code java> | ||
− | / | + | // Levantamos la configuración de spring. |
− | |||
− | |||
@ContextConfiguration(locations = {"classpath:groboutils-business.xml"}) | @ContextConfiguration(locations = {"classpath:groboutils-business.xml"}) | ||
@RunWith(SpringJUnit4ClassRunner.class) | @RunWith(SpringJUnit4ClassRunner.class) | ||
Línea 54: | Línea 52: | ||
private SleepManagerBo sleepManagerBo; | private SleepManagerBo sleepManagerBo; | ||
− | / | + | // Creamos una clase que al extender de TestRunnable, nos hace implementar |
− | + | // el método runTest(). En el mismo invocamos nuestro método de negocio. | |
− | |||
− | |||
public class HiloManager extends TestRunnable { | public class HiloManager extends TestRunnable { | ||
private Integer minimo; | private Integer minimo; |
Revisión del 15:39 8 jul 2010
Contenido
La situación
Muchas veces desarrollamos clases que se ejecutarán en hilos de manera concurrente. Dicha concurrencia suele ser propensa a errores que son difíciles de detectar y corregir por su naturaleza aleatoria. Por eso es una buena práctica sumar a nuestra batería de tests algunos escenarios que verifiquen el comportamiento del sistema cuando se ejecuta multihilo.
El problema
Si bien podríamos hacer un test de JUnit que cree varios hilos de ejecución, el runner (al menos hasta la version de Junit 4.5) no lo soporta: se crean los hilos y el test termina hayan o no terminado de ejecutar todos los hilos creados. Adicionalmente en el test que creó los hilos desconocemos el resultado de cada uno de estos hilos hijo, por lo que no podemos realizar asserts.
Una solución: GroboUtils
GroboUtils es un conjunto de sub-proyectos que se basan en JUnit para extender sus capacidades. En particular, veremos un ejemplo del subproyecto que se encarga de los tests multihilo.
La clase a ejecutar multihilo
SleepManagerStatelessBoImpl contiene un método para ejecutar un sleep durante una cantidad de milisegundos generada aleatoriamente en base a los valores minimo y maximo recibidos por parámetro. Si los milisegundos generados son mayores a 10000 lanza una exception.
public class SleepManagerStatelessBoImpl implements SleepManagerBo {
public Integer ejecutarSleep(Integer maximo, Integer minimo) throws InterruptedException { System.out.println("Thread: " + Thread.currentThread().getId() + " - Inicio"); Integer numeroAleatorio = (int) (Math.random() * (maximo - minimo)) + minimo;
if (numeroAleatorio > 10000) { throw new IllegalArgumentException("Numero mayor a 10000 milisegundos"); }
System.out.println("Thread: " + Thread.currentThread().getId() + " - Sleep: " + numeroAleatorio); Thread.sleep(numeroAleatorio); System.out.println("Thread: " + Thread.currentThread().getId() + " - Fin");
return numeroAleatorio; }
}
Configuración de spring en el archivo groboutils-business.xml:
<bean id="business.SleepManagerStatelessBo"
class="com.dosideas.groboutils.demo.business.impl.SleepManagerStatelessBoImpl"/>
Test multihilo - escenario: Todos los hilso ejecutan ok
// Levantamos la configuración de spring.
@ContextConfiguration(locations = {"classpath:groboutils-business.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class SleepManagerStatelessMultithreadTest {
@Qualifier("business.SleepManagerStatelessBo") @Autowired private SleepManagerBo sleepManagerBo;
// Creamos una clase que al extender de TestRunnable, nos hace implementar // el método runTest(). En el mismo invocamos nuestro método de negocio. public class HiloManager extends TestRunnable { private Integer minimo; private Integer maximo; private Integer resultado;
public HiloManager(Integer minimo, Integer maximo) { this.minimo = minimo; this.maximo = maximo; }
@Override public void runTest() throws Throwable { try { resultado = sleepManagerBo.ejecutarSleep(maximo, minimo); } catch (InterruptedException e) { e.printStackTrace(); } }
public Integer getResultado() { return resultado; } }
@Test public void sleepMultihilo_escenarioOk_verificamosGeneracionDeNumerosDistintos() throws Throwable { System.out.println("Inicia ejecucion multihilo");
// Instanciamos hilos para que se generen valores que no superen los // 10000 millisegundos HiloManager hilo1 = new HiloManager(1000, 2000); HiloManager hilo2 = new HiloManager(5000, 8000); HiloManager hilo3 = new HiloManager(6000, 7000);
// Pasamos el array de hilos a ejecutar al runner de grobbo que soporta // ejecucion multihilo. TestRunnable[] arrayDeHilos = {hilo1, hilo2, hilo3}; MultiThreadedTestRunner nultithreadTestRunner = new MultiThreadedTestRunner(arrayDeHilos); nultithreadTestRunner.runTestRunnables();
// Verificamos que se hayan generados 3 numeros aleatorios diferentes. assertNotSame(hilo1.getResultado(), hilo2.getResultado()); assertNotSame(hilo1.getResultado(), hilo3.getResultado()); assertNotSame(hilo2.getResultado(), hilo3.getResultado());
System.out.println("Fin ejecucion multihilo"); }
}