name.didier.david.test4j.testng.ThreadTestContext Maven / Gradle / Ivy
package name.didier.david.test4j.testng;
import static java.lang.String.format;
import java.lang.reflect.Method;
/**
* Facilitates thread testing by reporting back any failure which would not have been caught otherwise since it happened
* in a different thread. Usage:
*
*
* public class ThreadTest {
* protected ThreadTestContext threadTestContext;
*
* @BeforeMethod
* public void initializeThreadTestContext(Method method) {
* threadTestContext = new ThreadTestContext(method);
* }
*
* @Test
* public void test() {
* Thread thread = threadTestContext.start(myRunnable);
* waitForSomething();
* stopMyRunnable();
* }
*
* @AfterMethod
* public void checkThreadTestContext() {
* threadTestContext.check();
* }
* }
*
*
* @author ddidier
*/
public class ThreadTestContext {
/** The current test method. */
private final Method testMethod;
/** The thread which raised the exception if any. */
private Thread uncaughtExceptionThread;
/** The exception raised by the thread if any. */
private Throwable uncaughtException;
/**
* Default constructor.
*
* @param testMethod the current test method.
*/
public ThreadTestContext(final Method testMethod) {
super();
this.testMethod = testMethod;
}
/**
* Creates a new thread with the specified {@link Runnable} then starts it.
*
* @param runnable the thread target.
* @return a new started thread.
*/
public Thread start(final Runnable runnable) {
Thread thread = new Thread(runnable, testMethod.getName());
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread t, final Throwable e) {
uncaught(t, e);
}
});
thread.start();
return thread;
}
/**
* Creates a new thread with the specified {@link Runnable}, starts it, then waits for it to complete.
*
* @param runnable the thread target.
* @return a new completed thread.
*/
public Thread startAndJoin(final Runnable runnable) {
try {
Thread thread = start(runnable);
thread.join();
return thread;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Fails the test if {@code uncaughtExceptionThread} or {@code uncaughtException} is set.
*/
public void check() {
if (uncaughtException != null) {
throw new AssertionError(format("Uncaught error in thread '%s'", uncaughtExceptionThread.getName()),
uncaughtException);
}
}
/**
* Sets {@code uncaughtExceptionThread} and {@code uncaughtException} which will be used to determine if the test
* succeeded or failed.
*
* @param thread the thread which raised the exception.
* @param throwable the exception raised by the thread.
*/
protected void uncaught(final Thread thread, final Throwable throwable) {
this.uncaughtExceptionThread = thread;
this.uncaughtException = throwable;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy