您的位置:首页 > 移动开发 > Android开发

【Android单元测试系列】真正的异步单元测试

2015-06-25 15:27 399 查看

背景

参考了网上诸多的Android异步单元测试的方法之后,发现方法就两种,但是却没有发现这两种方法的一些关键说明,也正是少了这些关键说明,我绕了很大的圈子

方法一

public class ExampleInstrumentationTeseCase extends InstrumentationTestCase {

    private Activity mActivity;

    private Context mApplicationContext;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        Intent intent = new Intent();
        intent.setClassName("com.example.demo", TestcaseActivity.class.getName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mActivity = (TestcaseActivity) getInstrumentation().startActivitySync(intent);
        mApplicationContext = mActivity.getApplicationContext();

    }

    @Override
    protected void tearDown() throws Exception {
        mActivity.finish();
        try {
            super.tearDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.tearDown();
    }

    public void testAsyncTask() throws Throwable {
        final CountDownLatch signal = new CountDownLatch(1);

        // 在UI线程中执行异步操作
        runTestOnUiThread(new Runnable() {

            @Override
            public void run() {
                // 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
                new MyAsyncTask() {
                    @Override
                    protected void onPostExecute(String result) {
                        super.onPostExecute(result);
                        assertEquals("kale", result);
                        signal.countDown();

                    }
                }.execute();
            }
        });
        signal.await();
    }

}


方法二

public void testAsyncTask() throws Throwable {
        final CountDownLatch signal = new CountDownLatch(1);

        final String TDD = "TDD";

        // 在UI线程中执行异步操作
        runTestOnUiThread(new Runnable() {

            @Override
            public void run() {
                // 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
                new MyAsyncTask() {
                    @Override
                    protected void onPostExecute(String result) {
                        super.onPostExecute(result);
                        assertEquals("kale", result);
                        synchronized (TDD) {
                            TDD.notify();
                        }

                    }
                }.execute();
            }
        });
        synchronized (TDD) {
            TDD.notify();
        }
    }


分析&&关键点

上面两种实现方法其实很类似的,就是借助同步工具来进行阻塞辅助,而且网上很多地方都有这种代码,但是,实际上跑起来之后,发现是一直没有跑完的。

针对方法一来进行

分析:当执行assertEquals的时候,测试代码就结束了,也不会执行signal.countDown(),因此程序一直阻塞,导致没有跑完

于是,将
signal.countDown();
assertEquals("kale", result);
交换位置

public void testAsyncTask() throws Throwable {
        final CountDownLatch signal = new CountDownLatch(1);

        // 在UI线程中执行异步操作
        runTestOnUiThread(new Runnable() {

            @Override
            public void run() {
                // 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
                new MyAsyncTask() {
                    @Override
                    protected void onPostExecute(String result) {
                        super.onPostExecute(result);
                        signal.countDown();
                        assertEquals("kale", result);
                    }
                }.execute();
            }
        });
        signal.await();
        // mark1
    }


发现可以跑完了,但是无论如何都是测试通过的,即便值是不一样。

分析:当执行
signal.countDown();
之后,代码就会跳转到上面注释的mark1的位置继续执行,而不是执行
assertEquals("kale", result);
,因此无论断言的值是什么都会成功的,因为根本没有执行到断言那里


于是,再次修改代码,将回调中的值,用全局的私有变量缓存起来,然后在
signal.await();
方法后面才进行断言判断,于是得出

最终可行的代码

private String temp = null;

    public void testAsyncTask() throws Throwable {
        final CountDownLatch signal = new CountDownLatch(1);

        // 在UI线程中执行异步操作
        runTestOnUiThread(new Runnable() {

            @Override
            public void run() {
                // 执行异步任务,这个只是例子,没有实际的可以运行的代码,大家知道就好
                new MyAsyncTask() {
                    @Override
                    protected void onPostExecute(String result) {
                        super.onPostExecute(result);
                        temp = result;
                        signal.countDown();

                    }
                }.execute();
            }
        });
        signal.await();
        assertEquals("kale", temp);
    }


亲测可行~~,但是就是写起来有点怪异,因为一个测试方法用到全局全局变量来缓存
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: