【问题标题】:Testing WorkManager with custom initializer and Hilt使用自定义初始化程序和 Hilt 测试 WorkManager
【发布时间】:2022-12-24 01:32:05
【问题描述】:

我正在尝试为使用 Hilt 的 @AssistedInject 的自定义工作管理器实施仪器化测试。

我的工作管理器在应用程序中表现完美,但当我尝试根据 Google's work manager integration test guide 对其进行测试时,出现错误:

WM-WorkerFactory:java.lang.NoSuchMethodException:com.android.wmapp.data.SyncWorker。 [类 android.content.Context,类 androidx.work.WorkerParameters]

我已经关闭了 AndroidManifest.xml 中的默认初始化:

    <provider
        android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        tools:node="remove">
    </provider> 

在我的应用程序类中实现了 Configuration.Provider:

    @HiltAndroidApp
    class MyApplication : Application(), Configuration.Provider {
        @Inject
        lateinit var workerFactory: HiltWorkerFactory
        override fun getWorkManagerConfiguration(): Configuration {
            return Configuration.Builder().setWorkerFactory(workerFactory)
                .setMinimumLoggingLevel(android.util.Log.DEBUG).build()
        }
    }

设置我的 Worker 类:

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted applicationContext: Context,
    @Assisted workerParams: WorkerParameters,
    private val someRepository: SomeRepository,
    private val dispatchers: Dispatchers,
) : CoroutineWorker(applicationContext, workerParams) {
    override suspend fun doWork(): Result {
        val result = withContext(dispatchers.IO) {
            someRepository.synchronize()
        }
        return if (result) Result.success() else Result.retry()
    }
}

我库的测试build.gradle配置:

// Test
testImplementation 'junit:junit:4.+'
androidTestImplementation "androidx.work:work-testing:2.7.1"
androidTestImplementation "com.google.dagger:hilt-android-testing:2.43"
kaptAndroidTest "com.google.dagger:hilt-android-compiler:2.43"
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.43'
kaptAndroidTest 'androidx.hilt:hilt-compiler:1.0.0'
androidTestImplementation "androidx.test:runner:1.4.0"
androidTestImplementation "androidx.test:rules:1.4.0"
androidTestImplementation 'androidx.hilt:hilt-work:1.0.0'
implementation 'androidx.test.ext:junit-ktx:1.1.3'

我的仪器测试:

@HiltAndroidTest
class SyncWorkerTest {

    @get:Rule
    val hiltRule = HiltAndroidRule(this)
    private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext

    @Before
    fun setUp() {
        val config = Configuration.Builder()
            .setMinimumLoggingLevel(Log.DEBUG)
            .setExecutor(SynchronousExecutor())
            .build()
        WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
    }

    @Test
    fun testDoWork() {
        val request = SyncWorker.startSyncJob()

        val workManager = WorkManager.getInstance(context)
        val testDriver = WorkManagerTestInitHelper.getTestDriver(context)!!

        workManager.enqueueUniqueWork(
            SyncWorker.SyncWorkName,
            ExistingWorkPolicy.REPLACE,
            request,
        )

        val preRunWorkInfo = workManager.getWorkInfoById(request.id).get()

        Assert.assertEquals(WorkInfo.State.ENQUEUED, preRunWorkInfo.state)

        testDriver.setAllConstraintsMet(request.id)
    }
}

实现了我自己的 JUnitRunner 并在我的模块的 build.gradle 中指定了它:

    class YALTestRunner : AndroidJUnitRunner() {
        override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
            return super.newApplication(cl, HiltTestApplication::class.java.name, context)
        }
    }

testInstrumentationRunner "com.android.wmapp.YALTestRunner"

我在 WorkManager 的测试实施中遗漏了什么?

【问题讨论】:

    标签: android kotlin junit android-workmanager instrumented-test


    【解决方案1】:

    我认为您在清单中的配置错误。请检查这里。 2.6 及以后的版本应该有点不同:

    https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration#remove-default

    【讨论】:

    • 你好,亚沃尔。感谢您的关注。我尝试了不同的依赖项组合,您在我的示例中看到了这个,然后我尝试使用 sunflower's set,最后从 now in android 借用,但它仍然不起作用。所以我暂时放弃了。将等待文档中的更多示例。
    • 很遗憾听到这个消息。刀柄和匕首真是太棒了。它发展了多年,有 10 种不同的方法可以做一件事情。在这种情况下,通常我会尝试创建一些小应用程序并隔离我想做的事情,当它在我尝试集成的那一边工作时。我希望你成功。
    【解决方案2】:

    我会说这个问题可能是由于提供给initializeTestWorkManager方法的配置对象中缺少HiltWorkerFactory引起的。请尝试修改您的仪器测试:

    @HiltAndroidTest
    class SyncWorkerTest {
    
        @Inject
        lateinit var workerFactory: HiltWorkerFactory
    
        @get:Rule
        val hiltRule = HiltAndroidRule(this)
        private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
    
        @Before
        fun setUp() {
            hiltRule.inject()
        
            val config = Configuration.Builder()
                .setMinimumLoggingLevel(Log.DEBUG)
                .setExecutor(SynchronousExecutor())
                .setWorkerFactory(workerFactory)
                .build()
            WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
        }
    
        @Test
        fun testDoWork() {
            val request = SyncWorker.startSyncJob()
    
            val workManager = WorkManager.getInstance(context)
            val testDriver = WorkManagerTestInitHelper.getTestDriver(context)!!
    
            workManager.enqueueUniqueWork(
                SyncWorker.SyncWorkName,
                ExistingWorkPolicy.REPLACE,
                request,
            )
    
            val preRunWorkInfo = workManager.getWorkInfoById(request.id).get()
    
            Assert.assertEquals(WorkInfo.State.ENQUEUED, preRunWorkInfo.state)
    
            testDriver.setAllConstraintsMet(request.id)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 2016-08-25
      相关资源
      最近更新 更多