我试图测试一个方法,它在一个单独的线程中工作,简化如下:
public void methodToTest() { Thread thread = new Thread() { @Override public void run() { Clazz.i = 2; } }; thread.start(); }
在我的单元测试中,我想测试Clazz.i == 2,但是我不能这样做,因为我认为在线程更改值之前运行assert.我想到使用另一个线程来测试它,然后使用join来等待,但它仍然不起作用.
SSCCE:
@Test public void sscce() throws InterruptedException { Thread thread = new Thread() { @Override public void run() { methodToTest() } }; thread.start(); thread.join(); AssertEquals(2,Clazz.i); } public static class Clazz { public static int i = 0; }
我认为这是因为测试主代码创建一个等待(加入)到第二个线程的线程,但是第二个线程没有做这个工作,它创建另一个线程来完成工作,然后完成,这继续是第一个线程,而第三个线程在断言后执行Clazz.i = 2.
如何使它成为第一个线程等待它启动的线程以及该线程启动的任何线程?
解决方法
没有引用在methodToTest中创建的线程,你不能,很简单. Java没有提供找到“在特定时间段内产生的线程”的机制(即使是这样,这可能是一个使用丑的机制).
我看到,你有两个选择:
> Make methodToTest等待它产生的线程.当然,如果你明确地希望这是一个异步的动作,那么你不会很好地做到这一点.
>从methodToTest返回新创建的线程,以便任何调用者可以选择等待它.
可以注意到,第二选择可以以几种不同的方式来形成.例如,你可以返回一些抽象的类似Future
的对象而不是一个线程,如果你想扩展methodToTest的自由来使用各种各样的异步工作方法.您也可以定义一些全局任务池,您可以强制执行所有异步任务以在其中运行,然后等待池中的所有任务在检查断言之前完成.这样一个任务池可以采取ExecutorService
或ThreadGroup
的形式,或任何数量的其他形式.他们最终都做同样的事情,但可能或多或少适合于你的环境 – 主要的一点是,你必须明确地给调用者访问新创建的线程,是某种方式或另一种.