WorkManager fornisce le API per i test di Worker,
ListenableWorker e
ListenableWorker varianti
(CoroutineWorker)
e RxWorker).
Worker per i test
Supponiamo di avere un Worker simile a questo:
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(); } } }
Per testare questo Worker, puoi usare
TestWorkerBuilder Questo
aiuta a creare istanze di Worker che possono essere utilizzate ai fini di
testare la logica di business.
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())); } }
TestWorkerBuilder può essere utilizzato anche per impostare tag, ad esempio inputData o
runAttemptCount, in modo da poter verificare lo stato del worker in modo isolato. Prendi in considerazione
un esempio in cui SleepWorker prende la durata del sonno come dati di input
invece di essere una costante definita nel worker:
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, puoi fornire questi dati di input al tuo
TestWorkerBuilder per soddisfare le esigenze di SleepWorker.
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())); } }
Per maggiori dettagli sull'API TestWorkerBuilder, consulta la pagina di riferimento per
TestListenableWorkerBuilder,
la superclasse TestWorkerBuilder.
Test di ListenableWorker e delle sue varianti
Per testare un elemento ListenableWorker o la relativa
varianti (CoroutineWorker
e RxWorker), utilizza
TestListenableWorkerBuilder.
La differenza principale tra TestWorkerBuilder e a
TestListenableWorkerBuilder
è che TestWorkerBuilder ti consente di specificare lo sfondo Executor utilizzato
eseguire Worker, mentre TestListenableWorkerBuilder si basa
della logica di thread dell'implementazione di ListenableWorker.
Ad esempio, supponiamo di dover testare un CoroutineWorker che ha questo aspetto:
class SleepWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
delay(1000L) // milliseconds
return Result.success()
}
}
Per testare SleepWorker, creiamo prima un'istanza del worker utilizzando
TestListenableWorkerBuilder e quindi richiamare la relativa funzione doWork all'interno di un
coroutine.
@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 ha senso come strumento per la creazione di coroutine per i tuoi test, in modo che qualsiasi codice
che verrebbe eseguito in modo asincrono,
viene eseguito in parallelo.
Il test di un'implementazione RxWorker è simile al test di CoroutineWorker, poiché
TestListenableWorkerBuilder può gestire qualsiasi sottoclasse di ListenableWorker.
Prendi in considerazione una versione di SleepWorker che utilizzi RxJava anziché coroutine.
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); } }
Una versione di SleepWorkerTest che esegue il test di un RxWorker può essere simile alla
che ha testato un CoroutineWorker. Utilizzi lo stesso
TestListenableWorkerBuilder ma ora chiama createWork di RxWorker
personalizzata. createWork restituisce un Single che puoi utilizzare per verificare il
comportamento del worker. TestListenableWorkerBuilder gestisce tutti i thread
complessità ed esegue il codice worker in parallelo.
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()))); } }