WorkManager fornisce API per testare Worker,
ListenableWorker e le
varianti di ListenableWorker
(CoroutineWorker
e RxWorker).
Worker di test
Supponiamo di avere un Worker come questo:
class SleepWorker(context: Context, parameters: WorkerParameters) : Worker(context, parameters) { override fun doWork(): Result { // Sleep on a background thread. Thread.sleep(1000) return Result.success() } }
Per testare questo Worker, puoi utilizzare
TestWorkerBuilder. Questo builder aiuta a creare istanze di Worker che possono essere utilizzate per testare la logica di business.
// 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())) } }
TestWorkerBuilder può essere utilizzato anche per impostare tag, come inputData o runAttemptCount, in modo da poter verificare lo stato del worker in modo isolato. Considera un esempio in cui SleepWorker accetta una durata del sonno come dati di input anziché come costante definita nel worker:
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" } }
In SleepWorkerTest, puoi fornire questi dati di input al tuo TestWorkerBuilder per soddisfare le esigenze di SleepWorker.
// 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())) } }
Per maggiori dettagli sull'API TestWorkerBuilder, consulta la pagina di riferimento per TestListenableWorkerBuilder, la superclasse di TestWorkerBuilder.
Test di ListenableWorker e delle sue varianti
Per testare un ListenableWorker o le sue varianti (CoroutineWorker e RxWorker), utilizza TestListenableWorkerBuilder.
La differenza principale tra TestWorkerBuilder e un
TestListenableWorkerBuilder
è che TestWorkerBuilder ti consente di specificare il Executor in background utilizzato per
eseguire Worker, mentre TestListenableWorkerBuilder si basa sulla
logica di threading dell'implementazione di ListenableWorker.
Ad esempio, supponiamo di dover testare un CoroutineWorker simile al seguente:
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, quindi chiamiamo la relativa funzione doWork all'interno di una
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 è un generatore di coroutine adatto ai tuoi test, in modo che qualsiasi codice che verrebbe eseguito in modo asincrono venga invece eseguito in parallelo.
Il test di un'implementazione di RxWorker è simile al test di CoroutineWorker, poiché TestListenableWorkerBuilder può gestire qualsiasi sottoclasse di ListenableWorker.
Prendi in considerazione una versione di SleepWorker che utilizza RxJava anziché le coroutine.
class SleepWorker( context: Context, parameters: WorkerParameters ) : RxWorker(context, parameters) { override fun createWork(): Single<Result> { return Single.just(Result.success()) .delay(1000L, TimeUnit.MILLISECONDS) } }
Una versione di SleepWorkerTest che testa un RxWorker potrebbe essere simile alla versione che ha testato un CoroutineWorker. Utilizzi lo stesso TestListenableWorkerBuilder, ma ora chiami la funzione createWork di RxWorker. createWork restituisce un Single che puoi utilizzare per verificare il comportamento del worker. TestListenableWorkerBuilder gestisce tutte le complessità del threading ed esegue il codice del worker in parallelo.
@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())) } } }