WorkManager bietet APIs zum Testen von Worker
, ListenableWorker
und die ListenableWorker
Varianten (CoroutineWorker
) und RxWorker
).
Test-Worker
Angenommen, wir haben eine Worker
, die so aussieht:
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(); } } }
Zum Testen dieser Worker
können Sie Folgendes verwenden: TestWorkerBuilder
Dieses Builder erstellt Instanzen von Worker
, die zum Zweck von Testen der Geschäftslogik.
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())); } }
Mit TestWorkerBuilder
lassen sich auch Tags wie inputData
oder runAttemptCount
, damit Sie den Worker-Status isoliert prüfen können. Erwägen Sie Ein Beispiel, in dem SleepWorker
eine Schlafdauer als Eingabedaten annimmt und nicht als Konstante im Worker definiert:
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(); } } }
In SleepWorkerTest
können Sie diese Eingabedaten an Ihre TestWorkerBuilder
, um die Anforderungen von SleepWorker
zu erfüllen.
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())); } }
Weitere Informationen zur TestWorkerBuilder
API finden Sie auf der Referenzseite für TestListenableWorkerBuilder
, Die Basisklasse von TestWorkerBuilder
.
ListenableWorker und seine Varianten testen
Zum Testen eines ListenableWorker
oder seiner Varianten (CoroutineWorker
und RxWorker
), verwenden TestListenableWorkerBuilder
Der Hauptunterschied zwischen TestWorkerBuilder
und einem TestListenableWorkerBuilder
Mit TestWorkerBuilder
kannst du den Hintergrund angeben, mit dem Executor
führen Sie Worker
aus, während TestListenableWorkerBuilder
auf dem Threading-Logik der ListenableWorker
-Implementierung.
Angenommen, wir müssen ein CoroutineWorker
testen, das so aussieht:
class SleepWorker(context: Context, parameters: WorkerParameters) : CoroutineWorker(context, parameters) { override suspend fun doWork(): Result { delay(1000L) // milliseconds return Result.success() } }
Um SleepWorker
zu testen, erstellen wir zuerst eine Worker-Instanz mithilfe TestListenableWorkerBuilder
und rufen dann die Funktion doWork
innerhalb eines Koroutine verwenden.
@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, sodass jeder Code die asynchron ausgeführt wird, stattdessen parallel ausgeführt wird.
Das Testen einer RxWorker
-Implementierung ähnelt dem Testen von CoroutineWorker
, da TestListenableWorkerBuilder
kann jede abgeleitete Klasse von ListenableWorker
verarbeiten. Sehen Sie sich eine Version von SleepWorker
an, die RxJava anstelle von Koroutinen verwendet.
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); } }
Eine Version von SleepWorkerTest
, die ein RxWorker
testet, könnte ähnlich wie die Version, die CoroutineWorker
getestet hat. Sie verwenden die gleichen TestListenableWorkerBuilder
, ruft jetzt aber createWork
von RxWorker
an . createWork
gibt eine Single
zurück, mit der du das des Workers. TestListenableWorkerBuilder
verarbeitet alle Threads und Ihren Worker-Code parallel ausführt.
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()))); } }