LoginSignup
18
19

More than 5 years have passed since last update.

AsyncTaskのonPostExecuteまでのUnitTest

Posted at

AndroidのJUnitTestではAsyncTaskのexecuteメソッドの呼び出し時点で終了してしまうので、ちょっとした技が必要。

手段(1)
・内部ロジックを全てメソッドに書き出し、privateメソッドのテスト方法を用いてテスト
  →処理の単体テストには有効だが、onPreExecute~onPostExecuteの流れを含めてテストしたい場合にはできない

単体テストという意味では、(1)でも十分だが、Activityのテストを行っているとonPostExecuteからのキックを確認したい場合などが多くあるので、不十分。

手段(2)
・Taskが終わるのを待たせるようにする

ということで、(2)の実装例。

テストしたいAsyncのクラス

SampleTask.java
public class SampleTask extends AsyncTask<String, Integer, Integer> {
    EventListener listener = null;
    Context context =null;

    public interface EventListener{
        public void onFinish(int result);
    }

    public SampleTask(Context context, EventListener listener) {
        this.listener  =listener;
        this.context = context;
    }

    @Override
    protected Integer doInBackground(String... uID) {

        // なんか処理

        return 0;
    }
    @Override
    protected void onPostExecute(Integer result) {

        if(listener!=null){
            listener.onFinish(result);
        }
    }
}

テスト呼び出しコード

TestTask.java
public class TestTask extends ActivityInstrumentationTestCase2<MainActivity>{

    Activity mActivity = null;
    EventListener mListener = null;

    public TestTask(){
        super(MainActivity.class);
    }

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

        // アクティビティを取得
        mActivity = getActivity();
    }

    protected void tearDown() throws Exception {
        super.tearDown();
    }

    /**
       タスクを起動する
    */
    private void taskExecute(EventListener l) throws Throwable {
        // create CountDownLatch.
        final CountDownLatch signal = new CountDownLatch(1);

        mListener = l;

        runTestOnUiThread(new Runnable() {
            public void run() {
                try {
                    SampleTask task = new SampleTask (mActivity, new EventListener() {

                        public void onFinish(int result) {

                            if(mListener!=null){
                                mListener.onFinish(result);
                            }
                            signal.countDown(); // release
                        }
                    });
                    task.execute("nickname");
                } catch (Exception e) {
                    Log.e(TAG, "ERROR", e);
                    fail();
                }
            }
        });

        try {
            signal.await();// wait for callback
        } catch (InterruptedException e1) {
            fail();
            e1.printStackTrace();
        }
    }

    /** テストコード */
    public void test000() throws Throwable{
        // 前提処理かなにか

        // タスク呼び出し
        taskExecute(new EventListener() {
            public void onFinish(int result) {
                // ここに検証コードを書く
                assertTrue(0==result);
            }
        });
    }
}

参考:http://stackoverflow.com/questions/9774792/asynctask-onpostexecute-not-called-in-unit-test-case

上記参考頁との違いは、タスク呼び出し部分をメソッド化TestTask#taskExecuteしてあるところだけです。
SampleTask部分をテンプレートクラス化すれば、「AsyncTaskのJUnitTestを行うテストクラスの基本となる抽象クラス」が出来るかな。
気が向いたら追記します(笑)

18
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
19