O WorkManager fornece APIs para testar Worker,
ListenableWorker e as
variantes ListenableWorker
(CoroutineWorker
e RxWorker).
Testar workers
Suponhamos que temos um Worker parecido com o seguinte:
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(); } } }
Para testar Worker, você pode usar
TestWorkerBuilder. Esse
criador ajuda a criar instâncias do Worker que podem ser usadas com a finalidade de
testar a lógica de negócios.
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 também pode ser usado para definir tags, como inputData ou
runAttemptCount, para que você possa verificar o estado do worker isoladamente. Considere
um exemplo em que SleepWorker assume uma duração de suspensão como dados de entrada,
em vez de ser uma constante definida no 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(); } } }
Em SleepWorkerTest, você pode fornecer esses dados de entrada para seu
TestWorkerBuilder para atender às necessidades de 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())); } }
Para mais detalhes sobre a API TestWorkerBuilder, consulte a página de referência para
TestListenableWorkerBuilder,
a superclasse de TestWorkerBuilder.
Testar o ListenableWorker e as respectivas variantes
Para testar um ListenableWorker ou
as variantes (CoroutineWorker
e RxWorker ), use
TestListenableWorkerBuilder.
A principal diferença entre TestWorkerBuilder e um
TestListenableWorkerBuilder
é que TestWorkerBuilder permite que você especifique o Executor de segundo plano usado para
executar o Worker, enquanto TestListenableWorkerBuilder depende da
lógica de linha de execução da implementação de ListenableWorker.
Por exemplo, suponha que precisamos testar um CoroutineWorker parecido com o seguinte:
class SleepWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
delay(1000L) // milliseconds
return Result.success()
}
}
Para testar SleepWorker, primeiro criamos uma instância do Worker usando
TestListenableWorkerBuilder e, em seguida, chamamos a função doWork em uma
corrotina.
@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 faz sentido como um construtor de corrotinas para seus testes, de modo que qualquer código
executado de forma assíncrona é executado em paralelo.
Testar uma implementação de RxWorker é semelhante a testar CoroutineWorker, porque
TestListenableWorkerBuilder pode processar qualquer subclasse de ListenableWorker.
Considere uma versão de SleepWorker que use RxJava em vez de corrotinas.
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); } }
Uma versão de SleepWorkerTest que testa um RxWorker pode ser semelhante à
versão que testou um CoroutineWorker. Você usa o mesmo
TestListenableWorkerBuilder, mas agora chama a função createWork
do RxWorker. createWork retorna um Single que pode ser usado para verificar o
comportamento do worker. TestListenableWorkerBuilder processa as complexidades de linha de execução
e executa o código do worker em paralelo.
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()))); } }