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