tipos org ejemplo bool asserttrue asserts assertnotequals assertequals assertarrayequals array java junit assert

java - org - junit assert en thread throws exception



org.junit.assert maven (4)

El marco JUnit captura solo errores de aserciones en el hilo principal que ejecuta la prueba. No tiene conocimiento de excepciones desde dentro de nuevos hilos de generación. Para hacerlo bien, debe comunicar el estado de finalización del hilo al hilo principal. Debe sincronizar los subprocesos correctamente y usar algún tipo de variable compartida para indicar el resultado del subproceso anidado.

EDITAR:

Aquí hay una solución genérica que puede ayudar:

class AsynchTester{ private Thread thread; private volatile AssertionError exc; public AsynchTester(final Runnable runnable){ thread = new Thread(new Runnable(){ public void run(){ try{ runnable.run(); }catch(AssertionError e){ exc = e; } } }); } public void start(){ thread.start(); } public void test() throws InterruptedException{ thread.join(); if (exc != null) throw exc; } }

Debería pasarle el ejecutable en el constructor, y luego simplemente llamar a start () para activar, y test () para validar. El método de prueba esperará si es necesario y arrojará el error de aserción en el contexto del subproceso principal.

¿Qué estoy haciendo mal al lanzar una excepción en lugar de mostrar una falla, o no debería haber aserciones dentro de los hilos?

@Test public void testComplex() throws InterruptedException { int loops = 10; for (int i = 0; i < loops; i++) { final int j = i; new Thread() { @Override public void run() { ApiProxy.setEnvironmentForCurrentThread(env);//ignore this new CounterFactory().getCounter("test").increment();//ignore this too int count2 = new CounterFactory().getCounter("test").getCount();//ignore assertEquals(j, count2);//here be exceptions thrown. this is line 75 } }.start(); } Thread.sleep(5 * 1000); assertEquals(loops, new CounterFactory().getCounter("test").getCount()); }

StackTrace

Exception in thread "Thread-26" junit.framework.AssertionFailedError: expected:<5> but was:<6> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:277) at junit.framework.Assert.assertEquals(Assert.java:64) at junit.framework.Assert.assertEquals(Assert.java:195) at junit.framework.Assert.assertEquals(Assert.java:201) at com.bitdual.server.dao.ShardedCounterTest$3.run(ShardedCounterTest.java:77)


Cuando se trate de múltiples hilos de trabajo, como en la pregunta original, simplemente unirse a uno de ellos no es suficiente. Idealmente, querrá esperar a que se completen todos los subprocesos de trabajo mientras sigue informando los errores de aserción en el hilo principal, como en la respuesta de Eyal.

Aquí hay un ejemplo simple de cómo hacer esto usando ConcurrentUnit :

public class MyTest extends ConcurrentTestCase { @Test public void testComplex() throws Throwable { int loops = 10; for (int i = 0; i < loops; i++) { new Thread(new Runnable() { public void run() { threadAssertEquals(1, 1); resume(); } }).start(); } threadWait(100, loops); // Wait for 10 resume calls } }


Terminé usando este patrón, funciona con Runnables y Threads. Está inspirado principalmente en la respuesta de @Eyal Schneider:

private final class ThreadUnderTestWrapper extends ThreadUnderTest { private Exception ex; @Override public void run() { try { super.run(); } catch ( Exception ex ) { this.ex = ex; } } public Exception getException() throws InterruptedException { super.join(); // use runner.join here if you use a runnable. return ex; } }


Una pequeña mejora a la respuesta de Eyal Schneider :
El ExecutorService permite enviar un Callable y cualquier Excepción o Errores lanzados por el Future devuelto.
En consecuencia, la prueba se puede escribir como:

@Test public void test() throws Exception { ExecutorService es = Executors.newSingleThreadExecutor(); Future<?> future = es.submit(() -> { testSomethingThatMightThrowAssertionErrors(); return null; }); future.get(); // This will rethrow Exceptions and Errors as ExecutionException }