WorkManager bietet APIs zum Testen von Worker
, ListenableWorker
und den 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 dieses Worker
können Sie TestWorkerBuilder
verwenden. Mit diesem Builder können Sie Instanzen von Worker
erstellen, mit denen die Geschäftslogik getestet werden kann.
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
können auch Tags wie inputData
oder runAttemptCount
festgelegt werden, sodass Sie den Worker-Status isoliert prüfen können. Nehmen wir ein Beispiel, bei dem SleepWorker
eine Ruhedauer als Eingabedaten annimmt, anstatt sie im Worker als Konstante zu definieren:
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 für TestWorkerBuilder
bereitstellen, 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
, der Basisklasse von TestWorkerBuilder
.
ListenableWorker und seine Varianten testen
Verwenden Sie zum Testen eines ListenableWorker
oder seiner Varianten (CoroutineWorker
und RxWorker
) TestListenableWorkerBuilder
.
Der Hauptunterschied zwischen TestWorkerBuilder
und 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öchten 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()
}
}
Um SleepWorker
zu testen, erstellen wir zuerst mit TestListenableWorkerBuilder
eine Instanz des Workers und rufen dann die Funktion doWork
innerhalb 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 jeder Code, der asynchron ausgeführt 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.
Nehmen wir eine Version von SleepWorker
, 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
, mit der ein RxWorker
getestet wird, kann ähnlich aussehen wie die Version, mit der ein CoroutineWorker
getestet wurde. Sie verwenden dasselbe TestListenableWorkerBuilder
, rufen aber jetzt die createWork
-Funktion von RxWorker
auf. createWork
gibt ein Single
-Objekt zurück, mit dem Sie das Verhalten Ihres Workers prüfen können. TestListenableWorkerBuilder
verarbeitet alle Threading-Komplexitäten und führt den Worker-Code parallel aus.
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()))); } }