在多线程环境中使用JUnit时遇到了问题。以下代码应该失败,但它实际上传递了eclipse。
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
executor.submit(new Runnable() {
@Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
while (!isDone) {
Thread.sleep(1000);
}
}
}
这里是另一段代码,在这里我使用Future.get()等待线程停止,在这种情况下它将失败。
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
Future future=executor.submit(new Runnable() {
@Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
future.get();
}
}
我用Google搜索并发现JUnit无法处理多线程单元测试,但这两段代码之间的区别是什么?感谢
答案 0 :(得分:7)
JUnit无法查看运行测试的线程以外的线程中发生的异常。在第一种情况下,通过调用fail
发生异常,它发生在由executor
运行的单独线程中。因此,它对JUnit不可见,测试通过。
在第二种情况下,同一异常发生在executor
运行的单独线程中,但当您调用future.get
时,异常会有效地“报告回”测试线程。这是因为如果由于任何异常导致未来的计算失败,future.get
将抛出ExecutionException
。 JUnit能够看到此异常,因此测试失败。
答案 1 :(得分:2)
@zjffdu正如@ShiDoiSi所指出的,如果你有一个你想断言或失败的工作线程,Thread.join()可以正常工作。
如果你有多个工作线程,或者你想要更方便一点,那么有一个JUnit扩展用于执行多线程断言:ConcurrentUnit:
public class ExampleTest extends ConcurrentTestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
public void test() throws Throwable {
executor.submit(new Runnable() {
@Override
public void run() {
try {
threadFail("Failure message");
} finally {
resume();
}
}
});
threadWait();
}
}
祝你好运
答案 2 :(得分:1)
正如@ abhin4v指出的那样,新线程中的异常被吞噬了。您可以尝试提供自己的fail
- 与顶级线程同步的方法,就像您使用get()
的示例一样。
但是没有必要使用Futures,只需写入指示失败的共享变量并使用newThreadId.join()
。除此之外,我不知道在普通的JUnit中有任何其他解决方法。
答案 3 :(得分:0)
看看http://www.youtube.com/watch?v=wDN_EYUvUq0(从17:09开始),它解释了你可以通过JUnit和线程获得的问题。
我认为,在您的情况下,get()
会抛出ExecutionException
,这就是第二次测试失败的原因。在第一个测试用例中,jUnit没有看到异常。
答案 4 :(得分:0)
还有一个有趣的事实,Eclipse和IDEA可以在他们的junit测试运行器中生成一个VM,并最终在其上调用system.exit()。这意味着如果您在测试中没有正确等待(例如,当您在上面睡觉并希望任务已完成时),它可能会意外退出。有趣,但不完全是你所要求的!
有关详细信息,请参阅此link