您的位置:软件测试 > 开源软件测试 > 开源单元测试工具 > junit
Junit单元测试多线程的问题
作者:Mr.Yanphet 发布时间:[ 2016/8/18 11:24:34 ] 推荐标签:多线程 Junit 单元测试

  下午很快完成了一个接口的监控功能,然后屁颠屁颠地用Junit开始单元测试。然后我开始陷入崩溃的边缘...
  监控结束后需要将监控结果以邮件的形式发送给运营的小伙伴维护,前面测试还是很顺利,到了开多线程发邮件时不行了,
  程序也不报错,也接收不到邮件。然后改代码再测试,再冥思一会儿,再改再测试,还是无果,后选择度娘一下,结论是:
  Junit单元测试不支持多线程
  然后,整个人都不好了...浪费了我好多时间,是因为这个!!!
  虽然知道了结果,但是笔者还是需要亲自验证一下。
/**
* @Title: TestDoWork.java
* @Describe:
* @author: Mr.Yanphet
* @Email: mr_yanphet@163.com
* @date: 2016年8月15日 下午5:50:03
* @version: 1.0
*/
public class TestDoWork {
class DoWork implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
long milliSecond = System.currentTimeMillis();
System.out.println("i=" + i + ",milliSecond=" + milliSecond);// 输出循环次数和当前的系统时间
}
}
}
@Test
public void test() {
DoWork dw = new DoWork();
Thread t = new Thread(dw);
t.start();
}
}
  输出结果如下(笔者省略了部分输出):
  .....
  i=751,milliSecond=1471257586416
  i=752,milliSecond=1471257586416
  i=753,milliSecond=1471257586416
  i=754,milliSecond=1471257586416
  i=755,milliSecond=1471257586416
  i=756,milliSecond=1471257586416
  i=757,milliSecond=1471257586416
  i=758,milliSecond=1471257586416
  从结果可以看到,循环到了759次后没再输出了,说明子线程还没结束任务,整个程序被强迫结束了。
  既然知道了现象,那么为什么会出现这样的现象呢,贴出部分Junit4 TestRunner源码知道了
public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;
public static void main(String args[]) {
TestRunner aTestRunner = new TestRunner();
try {
TestResult r = aTestRunner.start(args);
if (!r.wasSuccessful())
System.exit(FAILURE_EXIT);
System.exit(SUCCESS_EXIT);
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
  再贴上TestResult部分源码,以供参考
protected  List<TestFailure>    fFailures
protected  List<TestFailure>    fErrors
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
public synchronized int errorCount() {
return fErrors.size();
}
public synchronized int failureCount() {
return fFailures.size();
}
  在TestRunner中可以看出,如果是单线程,当测试主线程执行结束后,不管子线程是否结束,都会回调TestResult的wasSuccessful方法,
  然后判断结果是成功还是失败,后调用相应的System.exit()方法。大家都知道这个方法是用来结束当前正在运行中的java虚拟机,jvm都
  自身难保了,所以子线程也对不住你咧...
  解决办法:
  1 简单粗暴地让主线程休眠一段时间,然后让子线程能够运行结束。但是这个方法的弊端是,你不知道子线程的运行时间,所以需要看脸=_=
  Thread.sleep();
  2 使用CountDownLatch工具类,让主线程阻塞,直到子线程运行结束或者阻塞超时,这个方法要比第一个方法好点。
  countDownLatch.await(5, TimeUnit.MINUTES);
  至于还有其他方法,笔者看到很多大神自己写的Junit支持多线程,有兴趣的读者自行度娘...

软件测试工具 | 联系我们 | 投诉建议 | 诚聘英才 | 申请使用列表 | 网站地图
沪ICP备07036474 2003-2017 版权所有 上海泽众软件科技有限公司 Shanghai ZeZhong Software Co.,Ltd