Reputation: 1236
I use WorkManager
in my app to chain multiple CoroutineWorkers
together. I am trying to test my app and have these workers run synchronously before continuing with rest of test.
As CoroutineWorker
is a suspend function it does not use the SynchronousExecutor()
provided to the workmanager Configuration
. The Android Docs mentions that CoroutineContext
can be provided to customise the thread the CoroutineWorker
is run on.
How can I provide a CoroutineContext
and have the worker run synchronously with the test code?
@Test
fun LaunchLongRunningCoroutineworkersWithWorkManager_FailsDueToAsynchronosity() {
hiltRule.inject()
context = InstrumentationRegistry.getInstrumentation().targetContext
val config = Configuration.Builder()
.setWorkerFactory(delegatingWorkerFactory)
.setExecutor(SynchronousExecutor())
.build()
WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
val workRequest1 = OneTimeWorkRequestBuilder<LongRunningCoroutineWorker1>()
.build()
val workRequest2 = OneTimeWorkRequestBuilder<LongRunningCoroutineWorker2>()
.build()
val workManager = WorkManager.getInstance(context)
workManager.beginUniqueWork("WORKNAME",ExistingWorkPolicy.REPLACE, workRequest1)
.then(workRequest2)
.enqueue()
val workInfo1 = workManager.getWorkInfoById(workRequest1.id).get()
val workInfo2 = workManager.getWorkInfoById(workRequest1.id).get()
/*fails expected: State.SUCCEEDED was: State.RUNNING*/
assertThat(workInfo1.state).isEqualTo(WorkInfo.State.SUCCEEDED)
assertThat(workInfo2.state).isEqualTo(WorkInfo.State.SUCCEEDED)
}
class LongRunningCoroutineWorker1(
val context: Context,
val parameters: WorkerParameters,
) : CoroutineWorker(context, parameters) {
override suspend fun doWork(): Result {
return withContext(Dispatchers.IO) {
/*simulate long work*/
delay(5000)
Result.success()
}
}
}
Upvotes: 0
Views: 2502
Reputation: 6476
Do not use the TestInitHelper
with CoroutineWorkers
(or RxWorker
). That helper function has been built for Worker classes.
WorkManager v2.1 introduces a new set of APIs to support a simpler way to test ListenableWorker classes and, as a consequence, CoroutineWorker. In our code we're going to use one of these new API: TestListenableWorkerBuilder.
Additional information is available in WorkManager's testing guide and a sample is available in the coroutine codelab, that also covers WorkManager.
In your case you should have something like:
@Test
fun LaunchLongRunningCoroutineworkersWithWorkManager_FailsDueToAsynchronosity() {
hiltRule.inject()
context = InstrumentationRegistry.getInstrumentation().targetContext
val worker1 = TestListenableWorkerBuilder<LongRunningCoroutineWorker1>(context)
.setWorkerFactory(delegatingWorkerFactory)
.build()
// "Manually" start the work
val result1 = worker1.startWork().get()
assertThat(result).isEqualTo(Result.success())
val worker2 = TestListenableWorkerBuilder<LongRunningCoroutineWorker2>(context)
.setWorkerFactory(delegatingWorkerFactory)
.build()
// "Manually" start the work
val result2 = worker1.startWork().get()
assertThat(result).isEqualTo(Result.success())
}
Upvotes: 1