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