Worker 実装のテスト

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

Worker のテスト

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

Kotlin

 class SleepWorker(context: Context, parameters: WorkerParameters) :     Worker(context, parameters) {      override fun doWork(): Result {         // Sleep on a background thread.         Thread.sleep(1000)         return Result.success()     } } 

Java

 public class SleepWorker extends Worker {     public SleepWorker(             @NonNull Context context,             @NonNull WorkerParameters workerParameters) {         super(context, workerParameters);     }      @NonNull     @Override     public Result doWork() {         try {             Thread.sleep(1000);         } catch (InterruptedException ignore) { return Result.success();         }     } } 

この Worker のテストには TestWorkerBuilder を使用できます。このビルダーで、ビジネス ロジックをテストするために使用する Worker のインスタンスを作成できます。

Kotlin

 // Kotlin code uses 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 = TestWorkerBuilderS<leepWorker(>             context = context,             executor = executor         ).build()          val result = worker.doWork()         assertThat(result, `is`(Result.success()))     } } 

Java

 @RunWith(AndroidJUnit4.class) public class SleepWorkerJavaTest {     private Context context;     private Executor executor;      @Before     public void setUp() {         context = ApplicationProvider.getApplicationContext();         executor = Executors.newSingleThreadExecutor();     }      @Test     public void testSleepWorker() {         SleepWorker worker =                 (SleepWorker) TestWorkerBuilder.from(context,                         SleepWorker.class,                         executor)                         .build();          Result result = worker.doWork();         assertThat(result, is(Result.success()));     } } 

また、TestWorkerBuilder を使用して inputDatarunAttemptCount などのタグを設定し、Worker の状態を個別に確認することもできます。次の例では、SleepWorker が Worker で定義された定数でなく、入力データとしてスリープ期間を取り込む場合を想定しています。

Kotlin

 class SleepWorker(context: Context, parameters: WorkerParameters) :     Worker(context, parameters) {      override fun doWork(): Result {         // Sleep on a background thread.         val sleepDuration = inputData.getLong(SLEEP_DURATION, 1000)         Thread.sleep(sleepDuration)         return Result.success()     }      companion object {         const val SLEEP_DURATION = "SLEEP_DURATION"     } } 

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();         }     } } 

SleepWorkerTest で、この入力データを TestWorkerBuilder に提供して、SleepWorker のニーズを満たすことができます。

Kotlin

 // Kotlin code uses 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 = TestWorkerBuilderS<leepWorker(>             context = context,             executor = executor,             inputData = workDataOf("SLEEP_DURATION" to 1000L)         ).build()          val result = worker.doWork()         assertThat(result, `is`(Result.success()))     } } 

Java

 @RunWith(AndroidJUnit4.class) public class SleepWorkerJavaTest {     private Context context;     private Executor executor;      @Before     public void setUp() {         context = ApplicationProvider.getApplicationContext();         executor = Executors.newSingleThreadExecutor();     }      @Test     public void testSleepWorker() {         Data inputData = new Data.Builder()                 .putLong("SLEEP_DURATION", 1000L)                 .build();          SleepWorker worker =                 (SleepWorker) TestWorkerBuilder.from(context,                         SleepWorker.class, executor)                         .setInputData(inputData)                         .build();          Result result = worker.doWork();         assertThat(result, is(Result.success()));     } } 

TestWorkerBuilder API について詳しくは、TestListenableWorkerBuilderTestWorkerBuilder のスーパークラス)のリファレンス ページをご覧ください。

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

ListenableWorker またはそのバリアント(CoroutineWorkerRxWorker)をテストするには、TestListenableWorkerBuilder を使用します。TestWorkerBuilderTestListenableWorkerBuilder の主な違いは、TestWorkerBuilderWorker の実行に使用されるバックグラウンド Executor を指定できるのに対し、TestListenableWorkerBuilderListenableWorker 実装のスレッド ロジックに依存する点です。

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

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

SleepWorker をテストするには、まず TestListenableWorkerBuilder を使用してワーカーのインスタンスを作成し、コルーチン内でその doWork 関数を呼び出します。

@RunWith(AndroidJUnit4::class) class SleepWorkerTest {     private lateinit var context: Context      @Before     fun setUp() {         context = ApplicationProvider.getApplicationContext()     }      @Test     fun testSleepWorker() {         val worker = TestListenableWorkerBuilder<SleepWorker>(context).build()         runBlocking {             val result = worker.doWork()             assertThat(result, `is`(Result.success()))         }     } } 

runBlocking はテストのコルーチン ビルダーとして機能し、非同期で実行されるコードは代わりに並列実行されます。

TestListenableWorkerBuilderListenableWorker のサブクラスを処理できるため、RxWorker 実装のテストは CoroutineWorker のテストと似ています。コルーチンではなく RxJava を使用する SleepWorker について考えてみましょう。

Kotlin

 class SleepWorker(     context: Context,     parameters: WorkerParameters ) : RxWorker(context, parameters) {     override fun createWork(): SingleR<esult >{         return Single.just(Result.success())             .delay(1000L, TimeUnit.MILLISECONDS)     } } 

Java

 public class SleepWorker extends RxWorker {     public SleepWorker(@NonNull Context appContext,  @NonNull WorkerParameters workerParams) {         super(appContext, workerParams);     }      @NonNull     @Override     public SingleR<esult >createWork() {         return Single.just(Result.success())                 .delay(1000L, TimeUnit.MILLISECONDS);     } } 

RxWorker をテストするバージョンの SleepWorkerTest は、CoroutineWorker をテストするバージョンと似ています。TestListenableWorkerBuilder を使用する点は同じです。ただし、このバージョンでは RxWorkercreateWork を呼び出します。createWorkSingle を返します。これを使用して、Worker の動作を確認できます。TestListenableWorkerBuilder が複雑なスレッド化を行い、Worker コードを並列実行します。

Kotlin

 @RunWith(AndroidJUnit4::class) class SleepWorkerTest {     private lateinit var context: Context      @Before     fun setUp() {         context = ApplicationProvider.getApplicationContext()     }      @Test     fun testSleepWorker() {         val worker = TestListenableWorkerBuilderS<leepWorker(>context).build()         worker.createWork().subscribe { result - >            assertThat(result, `is`(Result.success()))         }     } } 

Java

 @RunWith(AndroidJUnit4.class) public class SleepWorkerTest {     private Context context;      @Before     public void setUp() {         context = ApplicationProvider.getApplicationContext();     }      @Test     public void testSleepWorker() {         SleepWorker worker = TestListenableWorkerBuilder.from(context, SleepWorker.class)                 .build();         worker.createWork().subscribe(result - >                assertThat(result, is(Result.success())));         } }