ワーカーの実装のテスト

バージョン 2.1.0 以降の WorkManager には、WorkerListenableWorkerListenableWorker のバリアント(CoroutineWorkerRxWorker)をテストするための API が用意されています。

2.1.0 より以前のバージョンでは、ワーカーをテストするには、WorkManagerTestInitHelper を使用して WorkManager を初期化する必要がありました。バージョン 2.1.0 で Worker の実装をテストする場合、WorkManagerTestInitHelper を使用する必要はありません。

ListenableWorker とそのバリアントのテスト

ListenableWorker またはそのバリアント(CoroutineWorkerRxWorker)をテストするには、TestListenableWorkerBuilder を使用します。このビルダーで、Worker のビジネス ロジックをテストするために使用できる ListenableWorker のインスタンスを作成できます。

たとえば、次のような CoroutineWorker をテストする必要があるとします。

Kotlin

    class SleepWorker(context: Context, parameters: WorkerParameters) :
        CoroutineWorker(context, parameters) {
        override suspend fun doWork(): Result {
            delay(1000) // milliseconds
            return Result.success()
        }
    }

    

Java

    public class SleepWorker extends ListenableWorker {
        private final ResolvableFuture<Result> mResult;
        private final Handler mHandler;
        private final Object mLock;
        private Runnable mRunnable;
        public SleepWorker(
                @NonNull Context context,
                @NonNull WorkerParameters workerParameters) {
            super(context, workerParameters);
            mHandler = new Handler(Looper.getMainLooper());
            mResult = new ResolvableFuture<>();
            mLock = new Object();
        }

        @NonNull
        @Override
        public ListenableFuture<Result> startWork() {
            mRunnable = new Runnable() {
                @Override
                public void run() {
                    synchronized (mLock) {
                        mResult.set(Result.success());
                    }
                }
            };

            mHandler.postDelayed(mRunnable, 1000L);
            return mResult;
        }

        @Override
        public void onStopped() {
            super.onStopped();
            if (mRunnable != null) {
                mHandler.removeCallbacks(mRunnable);
            }
            synchronized (mLock) {
                if (!mResult.isDone()) {
                    mResult.set(Result.failure());
                }
            }
        }
    }

    

SleepWorker をテストするには、まず TestListenableWorkerBuilder を使用してワーカーのインスタンスを作成します。このビルダーを使用してタグ、inputDatarunAttemptCount なども設定できます。詳しくは、TestListenableWorker のリファレンス ページをご覧ください。

Kotlin

    @RunWith(AndroidJUnit4::class)
    class SleepWorkerTest {
        private lateinit var context: Context

        @Before
        fun setUp() {
            context = ApplicationProvider.getApplicationContext()
        }

        @Test
        fun testSleepWorker() {
            // Kotlin code can use the TestListenableWorkerBuilder extension to
            // build the ListenableWorker
            val worker = TestListenableWorkerBuilder<SleepWorker>(context).build()
            runBlocking {
                val result = worker.doWork()
                assertThat(result, `is`(Result.success()))
            }
        }
    }

    

Java

    @RunWith(AndroidJUnit4.class)
    public class SleepWorkerJavaTest {
        private Context mContext;

        @Before
        public void setUp() {
            mContext = ApplicationProvider.getApplicationContext();
        }

        @Test
        public void testSleepWorker() throws Exception {
           ListenableWorker worker =
               TestListenableWorkerBuilder.from(mContext, SleepWorker.class)
                       .build();

            Result result = worker.startWork().get();
            assertThat(result, is(Result.success()));
        }
    }
    

Worker のテスト

次のような Worker があるとします。

Kotlin

    class SleepWorker(context: Context, parameters: WorkerParameters) :
        Worker(context, parameters) {

        companion object {
            const val SLEEP_DURATION = "SLEEP_DURATION"
        }

        override fun doWork(): Result {
            // Sleep on a background thread.
            val sleepDuration = inputData.getLong(SLEEP_DURATION, 1000)
            Thread.sleep(sleepDuration)
            return Result.success()
        }
    }

    

Java

    public class SleepWorker extends Worker {
        public static final String SLEEP_DURATION = "SLEEP_DURATION";

        public SleepWorker(
                @NonNull Context context,
                @NonNull WorkerParameters workerParameters) {
            super(context, workerParameters);
        }

        @NonNull
        @Override
        public Result doWork() {
            try {
                long duration = getInputData().getLong(SLEEP_DURATION, 1000);
                Thread.sleep(duration);
            } catch (InterruptedException ignore) {
            }
            return Result.success();
        }
    }

    

この Worker のテストに TestWorkerBuilder を使用できるようになりました。TestWorkerBuilderTestListenableWorkerBuilder の主な違いは、TestWorkerBuilder では Worker の実行に使用されるバックグラウンド Executor を指定できる点です。

Kotlin

    // Kotlin code can use the TestWorkerBuilder extension to
    // build the Worker
    @RunWith(AndroidJUnit4::class)
    class SleepWorkerTest {
        private lateinit var context: Context
        private lateinit var executor: Executor

        @Before
        fun setUp() {
            context = ApplicationProvider.getApplicationContext()
            executor = Executors.newSingleThreadExecutor()
        }

        @Test
        fun testSleepWorker() {
            val worker = TestWorkerBuilder<SleepWorker>(
                context = context,
                executor = executor,
                inputData = workDataOf("SLEEP_DURATION" to 10000L)
            ).build()

            val result = worker.doWork()
            assertThat(result, `is`(Result.success()))
        }
    }

    

Java


    @RunWith(AndroidJUnit4.class)
    public class SleepWorkerJavaTest {
        private Context mContext;
        private Executor mExecutor;

        @Before
        public void setUp() {
            mContext = ApplicationProvider.getApplicationContext();
            mExecutor = Executors.newSingleThreadExecutor();
        }

        @Test
        public void testSleepWorker() {
            Data inputData = new Data.Builder()
                    .putLong("SLEEP_DURATION", 10_000L)
                    .build();

            SleepWorker worker =
                    (SleepWorker) TestWorkerBuilder.from(mContext,
                            SleepWorker.class,
                            mExecutor)
                            .setInputData(inputData)
                            .build();

            Result result = worker.doWork();
            assertThat(result, is(Result.success()));
        }
    }