zoukankan      html  css  js  c++  java
  • java单元测试之如何实现异步接口的测试案例

    测试是软件发布的重要环节,单元测试在实际开发中是一种常用的测试方法,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

  • 相关阅读:
    用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现
    spring-cloud-starter-hystrix(断路器)服务不通或者调用失败后的错误处理和回调
    spring-boot-starter-actuator(健康监控)配置和使用
    为什么Java使用System.getenv()获取刚刚设置的环境变量时为空
    Java获取系统环境变量(System Environment Variable)和系统属性(System Properties)以及启动参数的方法
    为什么Linux下的环境变量要用大写而不是小写
    Spring Boot在开发时实现热部署(开发时修改文件保存后自动重启应用)(spring-boot-devtools)
    Ubuntu 16.04添加多张虚拟网卡
    Javascript网址跳转方法
    MySQL出现:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Last packet sent to the server was 0 ms ago.
  • 原文地址:https://www.cnblogs.com/111testing/p/11111613.html
Copyright © 2011-2022 走看看