Robolectric3でandroid.os.Handler

2015-10-28T20:07:10+09:00 Java Android robolectric

android.os.Handlerを使う場合のテストのメモ

例を上げると

package kinjouj.app.oretter;

import java.util.BitSet;

import android.os.Handler;
import android.os.Looper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

@RunWith(RobolectricGradleTestRunner.class)
public class SampleTest {

    @Test
    public void test() {
        BitSet bs = new BitSet();
        SampleHandler.run(bs);
        assertThat(bs.get(0), is(true));
    }

    private static final class SampleHandler {

        private static final Handler handler = new Handler(Looper.getMainLooper());

        public static void run(final BitSet bitSet) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    bitSet.set(0);
                }
            }, 1000);
        }
    }
}

とやってもrunメソッドで作用するpostDelayedが作用するまで待ち処理しないと正常に作用しないはずなので

java.lang.AssertionError: 
Expected: is <true>
     but: was <false>

というようにテストが成功しない。こういう場合はShadowLooperなAPIを使えば良いとのこと

package kinjouj.app.oretter;

import java.util.BitSet;

import android.os.Handler;
import android.os.Looper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.shadows.ShadowLooper;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

@RunWith(RobolectricGradleTestRunner.class)
public class SampleTest {

    @Test
    public void test() {
        BitSet bs = new BitSet();
        SampleHandler.run(bs);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        assertThat(bs.get(0), is(true));
    }

    private static final class SampleHandler {

        private static final Handler handler = new Handler(Looper.getMainLooper());

        public static void run(final BitSet bitSet) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    bitSet.set(0);
                }
            }, 1000);
        }
    }
}

但し場合によってはnew Handlerをする引数にLooper.getMainLooper等を指定してないとRobolectricで正常に作用してくれない場合のケースも存在するっぽい

Robolectric3でDrawerLayoutをテスト fabric.io(Crashlytics)でクラッシュレポート