代码改变世界

java单元测试之如何实现异步接口的测试案例

2019-06-30 22:46  清风软件测试开发  阅读(5227)  评论(0编辑  收藏  举报

测试是软件发布的重要环节,单元测试在实际开发中是一种常用的测试方法,java单元测试主要用junit,最新是junit5,本人开发一般用junit4。因为单元测试能够在软件模块组合之前尽快发现问题,所以实际开发中投入产出比很高。实际使用难免会遇到异步操作的接口测试,最常用的情景是别人家的SDK封装了异步处理,需要用测试用例来验证SDK的流程,顺便测试参数的处理情况。由于异步testcase的会在调用后立即返回,异步线程执行完之前test线程已经结束了,无法验证测试最终结果。我们可以通过同步锁方法把异步接口转换为同步处理流程。
一、什么是单元测试?
单元测试是对软件最小实现单元进行的一种测试,例如C语言的函数,C++的类,java的类等。java有一套单元测试框架junit,Android中有AndroidTestCase等等。我们可以用junit对java函数,类,模块接口进行测试。

二、java单元测试教程
对于单元测试的教程网上有好多,这里就不再重复阐述了。
eclipse单元测试
http://tonl.iteye.com/blog/1948869
gradle构建junit单元测试教程
http://www.jianshu.com/p/e4e99b62a203

三、如何处理异步类型的单元测试
1. 能够获取Thread句柄的异步类型
对于有java thread句柄的测试类型,我们使用使用Thread.join函数等待线程执行完毕。
    @Test
    public void testExplicitThread() {
        System.out.println("testExplicitThread");
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("thread start.");
                try {
                    for (int i = 0; i < 5; i++) {
                        System.out.println("progress: " + i);
                        sleep(1000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println("thread finish.");
                }
            }
        };
        thread.start();
        try {
            thread.join(); // 等待线程执行完毕
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("testExplicitThread exit");
    }

测试用例输出:
testExplicitThread
thread start.
progress: 0
progress: 1
progress: 2
progress: 3
progress: 4
thread finish.
testExplicitThread exit

 

2. 没有thread句柄的异步单元测试
因为没有thread句柄,所以无法使用 join 函数。只能手动操作同步锁对异步接口进行同步
Object.wait 当前线程进入等待状态,直到其他线程调用 notify 或者 notifyAll 函数唤醒。
具体实现如下:

    /**
     * 回调接口
     */
    interface Callback {
        void onStart();
        void onProgress(int progress);
        void onFinish();
    }
 
    /**
     * 异步方法
     */
    static class AsyncDemo {
        private int len = 0;
        private Callback callback = null;
        public AsyncDemo(int len, Callback cb) {
            this.len = len;
            this.callback = cb;
        }
 
        public void doJob() {
            new Thread() {
                @Override
                public void run() {
                    if (null != callback) {
                        callback.onStart();
                    }
                    try {
                        for (int i = 0; i < len; i++) {
                            if (null != callback) {
                                callback.onProgress(i);
                            }
                            sleep(1000);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        if (null != callback) {
                            callback.onFinish();
                        }
                    }
                }
            }.start();
        }
    }
 
    private Object mLock = new Object(); // 同步锁
    private int mCount = 0; // 加解锁条件
 
    @Test
    public void testBlindCallback() {
        System.out.println("testBlindCallback");
        Callback cb = new Callback() {
 
            public void onStart() {
                System.out.println("onStart");
            }
 
            public void onProgress(int progress) {
                System.out.println("onProgress: " + progress);
            }
 
            public void onFinish() {
                System.out.println("onFinish");
                synchronized (mLock) {
                    mCount = 0;
                    mLock.notifyAll(); // 回调执行完毕,唤醒主线程
                }
            }
        };
        System.out.println("before AsyncDemo doJob");
        AsyncDemo demo = new AsyncDemo(5, cb);
        demo.doJob();
        synchronized (mLock) {
            mCount = 1;  // 设置锁条件
            while (mCount > 0) {
                try {
                mLock.wait(); // 等待唤醒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("after AsyncDemo doJob");
    }

测试输出结果:
testBlindCallback
before AsyncDemo doJob
onStart
onProgress: 0
onProgress: 1
onProgress: 2
onProgress: 3
onProgress: 4
onFinish
after AsyncDemo doJob


处理方法就是在测试线程执行异步接口后进入wait,等待回调退出接口(onFinish)唤醒test线程。

 



原文地址:https://blog.csdn.net/sweettool/article/details/75948237