执行摘要:当在线程中抛出断言错误时,单元测试不会死。这是有道理的,因为不应允许一个线程使另一个线程崩溃。问题是我如何 1) 在第一个辅助线程崩溃时使整个测试失败,或者 2) 在每个线程都完成后循环并确定每个线程的状态(参见下面的代码)。实现后者的一种方法是使用每个线程的状态变量,例如,“boolean[] statuses”并且“statuses[i] == false”意味着线程失败(这可以扩展以捕获更多信息)。但是,这不是我想要的:我希望它在抛出断言错误时像任何其他单元测试一样失败。这甚至可能吗?这是可取的吗?
我觉得无聊,我决定在我的单元测试中产生一堆线程,然后让它们调用一个服务方法,只是为了它。代码大致如下:
Thread[] threads = new Thread[MAX_THREADS];
for( int i = 0; i < threads.length; i++ ) {
threads[i] = new Thread( new Runnable() {
private final int ID = threadIdSequenceNumber++;
public void run() {
try {
resultRefs[ID] = runTest( Integer.toString( ID ) ); // returns an object
}
catch( Throwable t ) {
// this code is EVIL - it catches even
// Errors - don't copy it - more on this below
final String message = "error testing thread with id => "
+ ID;
logger.debug( message, t );
throw new IllegalStateException( message, t );
// need to wrap throwable in a
// run time exception so it will compile
}
}
} );
}
在此之后,我们将遍历线程数组并启动每个线程。之后,我们将等待他们全部完成。最后,我们将对结果引用进行一些检查。
for( Thread thread : threads )
thread.start();
logger.debug( "waiting for threads to finish ..." );
boolean done = false;
while( !done ) {
done = true;
for( Thread thread : threads )
if( thread.isAlive() )
done = false;
}
for( int i = 0; i < resultRefs.length; i++ ) {
assertTrue( "you've got the world messed, dawg!",
myCondition(resultRefs[i]) );
这就是问题所在。你注意到那个讨厌的 try-catch-throwable 块了吗?我只是将其添加为临时黑客,因此我可以看到发生了什么。在 runTest(String) 中进行了一些断言,例如 assertNotNull(null),但由于它在不同的线程中,它不会导致单元测试失败!!!!
我的猜测是,我们需要以某种方式遍历线程数组,检查每个线程的状态,如果线程以令人讨厌的方式终止,则手动导致断言错误。提供此信息的方法的名称是什么(死线程的堆栈跟踪)。