0%

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

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

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

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

首先想到是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@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 了...自然是没法返回断言的数据了.

于是,我又改了一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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测试用例也是支持的.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@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 许可协议。转载请注明出处!