java JUnit在多线程环境下的怪异问题

8xiog9wr  于 2022-12-21  发布在  Java
关注(0)|答案(4)|浏览(108)

我在多线程环境下使用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();
    }
}

我在谷歌上搜索了一下,发现JUnit不能处理多线程单元测试,但是这两段代码有什么区别呢?谢谢

vlju58qv

vlju58qv1#

JUnit无法看到在运行测试的线程以外的线程中发生的异常。在第一种情况下,通过调用fail发生异常,它发生在executor运行的单独线程中。因此,它对JUnit不可见,测试通过。
在第二种情况下,相同的异常发生在executor运行的单独线程中,但当您调用future.get时,该异常实际上被“报告回”给测试线程。这是因为如果未来的计算由于任何异常而失败,future.get将抛出ExecutionException。JUnit能够看到该异常,因此测试失败。

v64noz0r

v64noz0r2#

正如@abhin4v所指出的,新线程中的异常会被吞噬,你可以试着提供你自己的fail-方法,它与顶层线程同步,就像你的get()例子一样。
但是不需要使用Futures,只需要写入一个指示失败的共享变量并使用newThreadId.join()即可,除此之外,我不知道在普通JUnit中还有什么其他方法可以解决这个问题。

unhi4e5o

unhi4e5o3#

看一下http://www.youtube.com/watch?v=wDN_EYUvUq0(从17:09开始),它解释了JUnit和线程可能遇到的问题。
我认为,在您的例子中,get()抛出了一个ExecutionException,这就是第二个测试失败的原因,在第一个测试中,jUnit没有看到异常。

4nkexdtk

4nkexdtk4#

还有一个有趣的事实,Eclipse和IDEA可以在他们的junit测试运行器中生成一个VM,并最终在其上调用system.exit()。这意味着,如果您在测试中没有正确等待(例如,当您在上面睡觉并希望任务已经完成时),它可能会意外退出。有趣,但不完全是您所要求的!
有关详细信息,请参阅此link...

相关问题