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