0%

Java/Android编写异步的单元测试用例

不写单元测试用例的程序员不是一个好CTO!!!

注:以下内容编码环境为AndroidStudio_2.4Preview6,测试框架 JUnit4.12

今天在研究 MVP_RxJava2_Retrofit2_OkHttp3 ,打算写一个单元测试类测试一下今天的劳动成果.犯难了,之前写的单元测试类都是同步调用的,没有处理过异步的单元测试呀!

首先想到是这样的:

@Test
public void testQueryApi() throws Exception {
    // Context of the app under test.
    new QueryModelImpl().queryIp("8.8.8.8", new BasePresenterImpl.SubscriberEx<IpBean>() {
        @Override
        public void onSubscribeing(Subscription subscription) {
            subscription.request(Long.MAX_VALUE);
        }

        @Override
        public void onNext(IpBean bean) {
            assertTrue(null != bean);
        }

        @Override
        public void onError(Throwable e, boolean global) {
            super.onError(e, global);
            assertTrue(false);
        }
    });
}

然而...并没有什么卵用!断言根本不被执行...呵呵

仔细一想,嗯! testQueryApi() 应该是运行在主线程的,而我的 new QueryModelImpl().queryIp() 是异步的,也就是说 queryIp() 这个方法还没执行完(呵呵,可能初始化都还没走完),我们的主线程就已经死了,单元测试进程就 Game Over 了...自然是没法返回断言的数据了.

于是,我又改了一下:

@Test
public void testQueryApi() throws Exception {
    // Context of the app under test.
    final Object[] object = new Object[1];
    new QueryModelImpl().queryIp("8.8.8.8", new BasePresenterImpl.SubscriberEx<IpBean>() {
        @Override
        public void onSubscribeing(Subscription subscription) {
            subscription.request(Long.MAX_VALUE);
        }

        @Override
        public void onNext(IpBean bean) {
            object[0] = bean;
        }

        @Override
        public void onError(Throwable e, boolean global) {
            super.onError(e, global);
        }
    });
    Thread.sleep(10 * 1000);
    assertTrue(object[0] instanceof IpBean);
}

跑了下试试,额...确实可以了,但是勒,这简直太不优雅了吧!延时10秒是个什么鬼啊不过幸好,我的思路是OK的,这位我最后的改动打下了坚实的基础.阻塞住主线程,当异步线程响应的时候通知主线程就OK了于是呢,就有了一个类闪亮登场!!!(此处应有掌声)

CountDownLatch

该类属于 java.util.concurrent 包,所有对于普通Java测试用例也是支持的.

此类可以优雅的实现阻塞某个线程,直到得到一个通知或者超时.相比其他类实现相同的功能要简单很多(不能为了写单元测试去写一摩尔代码吧~),只有三句话而已~

@Test
public void testQueryApi() throws Exception {
    // Context of the app under test.
    final Object[] object = new Object[1];
    final CountDownLatch latch = new CountDownLatch(1);
    new QueryModelImpl().queryIp("8.8.8.8", new BasePresenterImpl.SubscriberEx<IpBean>() {
        @Override
        public void onSubscribeing(Subscription subscription) {
            subscription.request(Long.MAX_VALUE);
        }

        @Override
        public void onNext(IpBean bean) {
            object[0] = bean;
            latch.countDown();
        }

        @Override
        public void onError(Throwable e, boolean global) {
            super.onError(e, global);
            latch.countDown();
        }
    });
    latch.await();
    // latch.await(10 * 1000, TimeUnit.MILLISECONDS);
    assertTrue(object[0] instanceof IpBean);
}

OK,至此,异步单元测试用例已经写完了.

如果大家有更优美的方法~欢迎留言交流!

  • 本文作者: 6x
  • 本文链接: https://6xyun.cn/article/21
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-ND 许可协议。转载请注明出处!