非同期タスクをテストするテクニック

2082 ワード

非同期タスクをテストするとき、バックグラウンドスレッドがまだ完了していないが、テストスレッドが終了している場合がよくあります.この場合、正しいテスト結果が得られないことが多い.
最も簡単な方法は、5000ミリ秒などのテストにかかる可能性のある時間を推定し、テストを開始した後にThreadを呼び出すことです.sleep()メソッドは、テストスレッドをスリープさせ、テストが早く終わることを防止します.
public void testDoWork() throws Exception {

    //  
    doWork();

    Thread.sleep(6000);
}

上記の主な問題は、非同期タスクの実行時間が不確定であり、スリープ時間が推定できないことです.実はCountDownLatchを使うと、この問題を優雅に解決することができます.コードは以下の通りです.
public class TestDummy extends TestCase {

    private Dummy dummy;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        dummy = new Dummy();
    }

    public void testFoo() throws Exception {
        final CountDownLatch signal = new CountDownLatch(2);

        dummy.downloadInBg(" ", new OnFinishListener() {

            @Override
            public void onFinish(boolean ok) {
                assertTrue(ok);
                signal.countDown();
            }
        });

        dummy.downloadInBg(" ", new OnFinishListener() {

            @Override
            public void onFinish(boolean ok) {
                assertFalse(ok);
                signal.countDown();
            }
        });

        signal.await();
    }
}

class Dummy {

    void downloadInBg(final String password, final OnFinishListener listener) {
        new Thread() {
            public void run() {
                download(password, listener);
            }
        }.start();
    }

    void download(String password, OnFinishListener listener) {
        try {
            //  
            TimeUnit.SECONDS.sleep(1);
            if (!password.equals(" ")) {
                throw new Exception();
            }

            //  
            TimeUnit.SECONDS.sleep(5);
            listener.onFinish(true);
        } catch (InterruptedException e) {
            listener.onFinish(false);
        } catch (Exception e) {
            listener.onFinish(false);
        }
    }

    interface OnFinishListener {
        void onFinish(boolean ok);
    }
}

参考:Androidで非同期タスクをテストする