WorkManager bietet APIs zum Testen von Worker, ListenableWorker und den ListenableWorker-Varianten (CoroutineWorker und RxWorker).
Worker testen
Angenommen, wir haben ein Worker, das so aussieht:
class SleepWorker(context: Context, parameters: WorkerParameters) : Worker(context, parameters) { override fun doWork(): Result { // Sleep on a background thread. Thread.sleep(1000) return Result.success() } }
Zum Testen dieses Worker können Sie TestWorkerBuilder verwenden. Mit diesem Builder können Sie Instanzen von Worker erstellen, die zum Testen der Geschäftslogik verwendet werden können.
// 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 = TestWorkerBuilder<SleepWorker>( context = context, executor = executor ).build() val result = worker.doWork() assertThat(result, `is`(Result.success())) } }
TestWorkerBuilder kann auch verwendet werden, um Tags wie inputData oder runAttemptCount festzulegen, damit Sie den Worker-Status isoliert prüfen können. Angenommen, SleepWorker verwendet eine Schlafdauer als Eingabedaten, anstatt dass sie als Konstante im Worker definiert ist:
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" } }
In SleepWorkerTest können Sie diese Eingabedaten für TestWorkerBuilder bereitstellen, um die Anforderungen von SleepWorker zu erfüllen.
// 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 = TestWorkerBuilder<SleepWorker>( context = context, executor = executor, inputData = workDataOf("SLEEP_DURATION" to 1000L) ).build() val result = worker.doWork() assertThat(result, `is`(Result.success())) } }
Weitere Informationen zur TestWorkerBuilder API finden Sie auf der Referenzseite für TestListenableWorkerBuilder, die Basisklasse von TestWorkerBuilder.
ListenableWorker und seine Varianten testen
Verwenden Sie TestListenableWorkerBuilder, um einen ListenableWorker oder seine Varianten (CoroutineWorker und RxWorker) zu testen.
Der Hauptunterschied zwischen TestWorkerBuilder und einem TestListenableWorkerBuilder besteht darin, dass Sie mit TestWorkerBuilder den Hintergrund-Executor angeben können, der zum Ausführen des Worker verwendet wird, während TestListenableWorkerBuilder auf der Threading-Logik der ListenableWorker-Implementierung basiert.
Angenommen, wir müssen eine CoroutineWorker testen, die so aussieht:
class SleepWorker(context: Context, parameters: WorkerParameters) : CoroutineWorker(context, parameters) { override suspend fun doWork(): Result { delay(1000L) // milliseconds return Result.success() } }
Zum Testen von SleepWorker erstellen wir zuerst eine Instanz des Workers mit TestListenableWorkerBuilder und rufen dann die Funktion doWork in einer Koroutine auf.
@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 ist als Coroutine-Builder für Ihre Tests sinnvoll, damit Code, der asynchron ausgeführt werden würde, stattdessen parallel ausgeführt wird.
Das Testen einer RxWorker-Implementierung ähnelt dem Testen von CoroutineWorker, da TestListenableWorkerBuilder jede abgeleitete Klasse von ListenableWorker verarbeiten kann.
Betrachten wir eine Version von SleepWorker, die RxJava anstelle von Koroutinen verwendet.
class SleepWorker( context: Context, parameters: WorkerParameters ) : RxWorker(context, parameters) { override fun createWork(): Single<Result> { return Single.just(Result.success()) .delay(1000L, TimeUnit.MILLISECONDS) } }
Eine Version von SleepWorkerTest, die einen RxWorker testet, kann der Version ähneln, die einen CoroutineWorker getestet hat. Sie verwenden dieselbe TestListenableWorkerBuilder, rufen aber jetzt die Funktion createWork von RxWorker auf. createWork gibt ein Single zurück, mit dem Sie das Verhalten Ihres Workers prüfen können. TestListenableWorkerBuilder übernimmt die Threading-Komplexität und führt den Worker-Code parallel aus.
@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() worker.createWork().subscribe { result -> assertThat(result, `is`(Result.success())) } } }