今天下午很快完成了一个接口的监控功能,然后屁颠屁颠地用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支持多线程,有兴趣的读者自行度娘...

Junit单元测试多线程的问题的更多相关文章

  1. junit单元测试(keeps the bar green to keeps the code clean)

    error是程序错误,failure是测试错误. junit概要: JUnit是由 Erich Gamma (设计模式的创始人)和 Kent Beck (敏捷开发的创始人之一)编写的一个回归测试框架( ...

  2. spring && Cobertura && maven &&junit 单元测试以及测试覆盖率

    1. 目的:       junit 单元测试,Cobertura   测试覆盖率报告       项目目录结构          2. maven 配置     <project xmlns= ...

  3. 解决Junit单元测试 找不到类 ----指定Java Build Path

    做junit 单元测试时,发现怎么执行都是以前编译过得代码. 最后找到原因了, src/test/java 编译完的.class路径是 Default output folder Default ou ...

  4. JUnit单元测试框架的使用

    http://blog.csdn.net/mao520741111/article/details/51462215 原文地址 http://www.open-open.com/lib/view/op ...

  5. Java 工具 JUnit单元测试

    Java 工具 JUnit单元测试 @author ixenos 1.1.   JUnit单元测试框架的基本使用 一.搭建环境: 导入junit.jar包(junit4) 二.写测试类: 0,一般一个 ...

  6. Spring框架中整合JUnit单元测试的方法

    一. 步骤: 1. 拷贝jar包: 1. JUnit-4.9.jar和spring-test-4.2.4.RELEASE.jar ; 2. 替换原来的main函数: 1. 在测试类上使用注解方式替换: ...

  7. spring框架学习(三)junit单元测试

    spring框架学习(三)junit单元测试 单元测试不是头一次听说了,但只是听说从来没有用过.一个模块怎么测试呢,是不是得专门为一单元写一个测试程序,然后将测试单元代码拿过来测试? 我是这么想的.学 ...

  8. 备忘:Junit单元测试

    junit 目前测试都是在main方法中调用目前的结果都需要人工对比是否是想要的 1.使用Junit测试方法,绿色条条代表方法测试成功,没有bug,如果是红色条条代表有异常,测试不通过2.点击方法名. ...

  9. 单元测试系列:JUnit单元测试规范

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6762032.html Junit测试代 ...

随机推荐

  1. [转]JavaScript和html5 canvas生成圆形印章

    本文转自:http://www.cnblogs.com/dragondean/p/6013529.html 代码: function createSeal(id,company,name){ var ...

  2. PHP学习4——面向对象

    主要内容: 创建类 成员方法 构造方法 析构方法 封装 继承 接口 多态 静态成员 常用关键字 常用魔术方法 从PHP5开始引入了面向对象的全部机制,面向对象的特性符合软件工程的3个目标:重用性,灵活 ...

  3. Java - 避免不必要的对象

    通常,我们更喜欢重用一个对象而不是重新创建一个.如果对象是不可变的,它就始终可以被重用. 下面是一个反面例子: String s = new String("stringette" ...

  4. golang学习之mgo操作mongodb

    mgo是mongodb的golang驱动,测试代码: // mgotest project main.go package main import ( "fmt" "ti ...

  5. SpringCloud实战之初级入门(一)— eureka注册中心

    目录 写在前面 1.资料目录 2.环境介绍 3.eureka注册中心 3.1 创建工程 3.2 启动工程 5.eureka注册中心集群高可用 6.结语 7.一点点重要的事情 写在前面 我在软件行业浸泡 ...

  6. 前端(五):JavaScript面向对象之内建对象

    一.数据类型 js中数据类型分为两种,原始数据累次能够和引用数据类型. 1.原始数据类型 Undefined.Null.Boolean.Number.String是js中五种原始数据类型(primit ...

  7. node.js缓存处理方式

    Node.JS缓存处理分为客户端和服务端两个部分. 客户端的缓存主要是利用浏览器对HTTP协议响应头中cache-control和expires字段的支持.浏览器在得到明确的响应头后,会将文件缓存在本 ...

  8. cf1043E. Mysterious Crime(二分 前缀和)

    题意 题目链接 Sol 考场上做完前四题的时候大概还剩半个小时吧,那时候已经困的不行了. 看了看E发现好像很可做?? 又仔细看了几眼发现这不是sb题么... 先考虑两个人,假设贡献分别为\((x, y ...

  9. 提升PPT制作效率和颜值

    [大咖分享]By汤帅,PPT定制师 网站有时比素材库更有效 学会多模板整合利用 网站推荐:花瓣,officeplus,演界网,pptstore 演讲提纲 思维导图听课笔记

  10. Vue入门基础(火柴)

    前言 由于个人十分欣赏博友——小火柴的蓝色理想,他的博文我看了大多数,觉得十分的精彩,然而很多都是看后即忘.我想除了没有经常动手敲代码,更可能是在看的时候忽略了很多细节,因此打算把他的博文通通给“抄袭 ...