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

摘要:
测试是软件发布的重要部分。单元测试是实际开发中常用的测试方法。Java单元测试主要使用junit,最新的是junit5,我的开发一般使用junit4。因为单元测试可以在软件模块组合之前尽快发现问题,所以实际开发中的投入产出比非常高。单元测试是对软件的最小实现单元的一种测试,例如C语言函数、C++类、java类等。我们可以使用junit来测试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

免责声明:文章转载自《java单元测试之如何实现异步接口的测试案例》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇jquery-qrcode 生成和读取二维码www.nocmd.com 精品软件 坚持绿色之路 共筑生态之基下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Go(四) 并发编程

一、基本概念 并行和并发 并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。 需要CPU多核 并发(concurrency):指在同一时刻只能有一条指令执行,当多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行,只是时间分成若干段,通过CPU时间片轮转使得多个进程快速交替执行。 进程并发...

转 MYSQL监控工具--mytop

MYSQL监控工具--mytop   https://mp.weixin.qq.com/s/1X_uZaajImRRmpAsdLsNGw mysql可以说如今最为流行的数据库了,虽然现在nosql的风头正盛。但我想很多公司重要的业务数据不会用nosql去跑。而在这些方面mysql似乎的使用更盛(开源免费,让我花钱去买oracle,我想我是不会买的)。君...

Java面试——多线程面试题总结

0.前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分,本文汇总了常见的一些多线程面试题。 一些问题,比如volatile关键词的作用,synchronized和ReentrantLock的区别,wait()和sleep()的区别等等问题,已经在之前写过的文章中提到过了,这里就不赘述了,有兴趣可以查看以下几篇文章:Java并发——线程同...

虚拟化技术实现 — KVM 的 CPU 虚拟化

目录 文章目录 目录 前文列表 x86 体系结构的虚拟化 硬件辅助的 CPU 虚拟化 由 VMX 切换支撑的 CPU 虚拟化技术 KVM 的 CPU 虚拟化实现 vCPU 的调度方式 客户机 CPU 拓扑和模型 虚拟机 vCPU 数量分配原则 总结 参考文档 前文列表 《虚拟化技术实现 — 虚拟化技术发展编年史》《虚拟化技术实现 — QEMU-...

Java多线程 -yield用法

 前几天复习了一下多线程,发现有许多网上讲的都很抽象,所以,自己把网上的一些案例总结了一下!  一. Thread.yield( )方法:  使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了。 ...

Android网络通信库Volley简介

Android网络通信库Volley简介 Posted onMay 27, 2013byliubin 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google I/O 20...