zoukankan      html  css  js  c++  java
  • 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支持多线程,有兴趣的读者自行度娘...

  • 相关阅读:
    基因数据分析主流软件与基因预测方法步骤-搬运工
    调用约定__cdecl __fastcall与__stdcall
    const用法体会
    NS3系列——eclipse + NS3环境搭建
    小div在大div里面水平垂直都居中的实现方法
    template.js插件和ajax一起使用的例子
    js获取时间的函数集
    ajax获取json数据及实现跨域请求
    JavaScript里的Date 对象属性及对象方法--实现简单的日历
    css单行文本及多行文本溢出显示省略号
  • 原文地址:https://www.cnblogs.com/yanphet/p/5774291.html
Copyright © 2011-2022 走看看