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 = TestWorkerBuilder<SleepWorker>( 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 = TestWorkerBuilder<SleepWorker>( 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(): Single<Result> { 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 Single<Result> 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 = TestListenableWorkerBuilder<SleepWorker>(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()))); } }