我从PeriodicWorkRequest
创建了一个SyncDatabaseWorker
,如下所示:
class SyncDatabaseWorker(ctx: Context, params: WorkerParameters) : RxWorker(ctx, params) {
private val dataManager: DataManager = App.getDataManager()
override fun createWork(): Single<Result> {
return Single.create { emitter ->
dataManager.loadStoresFromServer()
.subscribe(object : SingleObserver<List<Store>> {
override fun onSubscribe(d: Disposable) {
}
override fun onSuccess(storeList: List<Store>) {
if (!storeList.isEmpty()) {
emitter.onSuccess(Result.success())
} else {
emitter.onSuccess(Result.retry())
}
}
override fun onError(e: Throwable) {
emitter.onSuccess(Result.failure())
}
})
}
}
companion object {
fun prepareSyncDBWorker(): PeriodicWorkRequest {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val myWorkBuilder = PeriodicWorkRequest.Builder(SyncDatabaseWorker::class.java, 7, TimeUnit.DAYS)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.DAYS) // Backoff retry after 1 day
.setConstraints(constraints)
return myWorkBuilder.build()
}
}
}
然后我像这样在Google's guide上编写单元测试:
@RunWith(AndroidJUnit4::class)
class SyncDatabaseWorkerTest {
private lateinit var context: Context
@Before
fun setup() {
context = InstrumentationRegistry.getInstrumentation().targetContext
val config = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setExecutor(SynchronousExecutor())
.build()
// Initialize WorkManager for instrumentation tests.
WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
}
@Test
@Throws(Exception::class)
fun testPeriodicWork_WithConstrains() {
// Create request
val request = SyncDatabaseWorker.prepareSyncDBWorker()
val workManager = WorkManager.getInstance(context)
val testDriver = WorkManagerTestInitHelper.getTestDriver(context)
// Enqueue and wait for result.
workManager.enqueue(request).result.get()
// Check work request is enqueued
var workInfo = workManager.getWorkInfoById(request.id).get()
assertThat(workInfo.state, `is`(WorkInfo.State.ENQUEUED))
// Tells the testing framework the period delay & all constrains is met
testDriver!!.setPeriodDelayMet(request.id)
testDriver.setAllConstraintsMet(request.id)
// Check work request is running
workInfo = workManager.getWorkInfoById(request.id).get()
assertThat(workInfo.state, `is`(WorkInfo.State.RUNNING))
}
}
即使满足期间延迟和所有约束,它始终处于ENQUEUED
状态。
Expected: is <RUNNING>
but: was <ENQUEUED>
当我调试测试并发现createWork(): Single<Result>
方法也被触发时,为什么状态不是RUNNING
?
这种方法可能是我错了,但是有关单元测试WorkManager的文档现在很少了,我不知道正确的方法。
答案 0 :(得分:1)
由于您使用的是同步执行器,因此您永远不会真正看到处于RUNNING
状态的工作-它应该已经执行了。我怀疑您的工作实际上已被标记为重试,因此再次进入ENQUEUED
状态。您应该可以通过设置断点或查看日志来验证这一点。
答案 1 :(得分:1)
鉴于您正在使用PeriodicWorkRequest
执行SynchronousExecutor
,您将永远不会看到WorkRequest
处于RUNNING
状态。在您断言它位于RUNNING
中之前,它将完成执行。
在您的Result.success()
中返回Result.failure()
或doWork()
之后,WorkRequest
回到下一个期间的ENQUEUED
(假设这是定期的请求)。