不写单元测试用例的程序员不是一个好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,至此,异步单元测试用例已经写完了.
如果大家有更优美的方法~欢迎留言交流!