UT中告别sleep使用assertWait校验结果

前言

在编写异步相关的测试用例时,不知道有没有同学粗暴地使用过Thread.sleep尝试地等待一个时长,然后去查询校验结果,本地运行断言全都通过,但到了CI环境中,确无法通过?所以又粗暴地增加了等待时长。
或者优雅一点使用过CountDownLatch,但使用这种方式往往会对异步执行逻辑产生侵入。所以我们可能想到:能否有一个循环判断逻辑外加一个最大等待时间。在限定的等待时间内,不断尝试获取校验异步逻辑的结果。

尝试assertWait

基于上述需求,很自然地写出如下功能函数:

    public static boolean assertWait(int millis, Supplier supplier) {
        Boolean flag = supplier.get();
        long current = System.currentTimeMillis();
        while (!flag && System.currentTimeMillis() - current < millis) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                flag = supplier.get();
            }
        }
        return flag;
    }

接下来我们看下上述代码存在哪些问题:

  • supplier为空代表何意?
  • 超时的时间精度固定100ms,是否合适?
  • supplier.get调用了两次,能复用吗?
  • supplier.get某些情况下,阻塞较长时间,超时设置会失效
  • sleep方法会不会让出CPU?好像还有争论

优化assertWait

针对性解答,如下:

  • supplier为空代表无判断逻辑,等同于等待millis时长
  • 不合适,所以以20毫秒为最小精度,同时兼顾等待时长,避免频繁判断
  • 能,使用do…while
  • 使用waitTime单独计时
  • 详细参考:https://www.jb51.net/article/87724.htm
       public static void assertWait2(long millis, Supplier supplier) {
        boolean result = false;
        long spin = Math.max(millis / 1000, 20);
        Duration duration = Duration.ofMillis(millis);
        long waitTime = 0;
        do {
            result = supplier != null && supplier.get();
            if (result) {
                break;
            }
            try {
                synchronized (duration) {
                    duration.wait(spin);
                }
                waitTime += spin;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (!result && waitTime < millis);//从IDE的提示看!result 一直为true等效于while (waitTime < millis);
        return result;
    }

    public static void assertWait2(int timeout, TimeUnit unit, Supplier supplier){
        long millis = unit.toMillis(timeout);
        return assertWait2(millis,supplier);
    }
结果   UT   sleep
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章