简体   繁体   English

使用 Hilt 和 WorkManager 进行仪器测试

[英]Instrumentation Tests using Hilt and WorkManager

I have an app that uses WorkManager to upload data to a server.我有一个应用程序使用 WorkManager 将数据上传到服务器。 I have end to end instrumentation tests written for the app that exercise several features including using work manager to upload the data.我已经为该应用程序编写了端到端的仪器测试,这些测试运用了多项功能,包括使用工作管理器上传数据。 The app is currently using Dagger2 and I'm trying to upgrade to use Hilt and running into some issues getting instrumentation tests running.该应用程序目前正在使用 Dagger2,我正在尝试升级以使用 Hilt,但在运行仪器测试时遇到了一些问题。

The documentation for using Hilt with WorkManager is straightforward and recommends adding this to your Application class to setup work manager:将 Hilt 与 WorkManager 结合使用的文档非常简单,建议将其添加到您的应用程序 class 中以设置工作管理器:

@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {

  @Inject lateinit var workerFactory: HiltWorkerFactory

  override fun getWorkManagerConfiguration() =
      Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

That works and I can run my app and use the features that use WorkManager.这行得通,我可以运行我的应用程序并使用使用 WorkManager 的功能。 But now I need to run instrumentation tests and Hilt recommends using the provided HiltTestApplication as the Application class when running the instrumentation tests.但现在我需要运行仪器测试,并且 Hilt 建议在运行仪器测试时使用提供的 HiltTestApplication 作为应用程序 class。 This doesn't work for my app, because my app requires work manager to be fully functional, which requires my app's customized application class to exist.这对我的应用程序不起作用,因为我的应用程序需要工作管理器才能正常运行,这需要我的应用程序的自定义应用程序 class 存在。 Hilt has a workaround for this problem and it allows you to provide your own test application class in the instrumentation tests. Hilt 有解决此问题的方法,它允许您在仪器测试中提供自己的测试应用程序 class。

@CustomTestApplication(BaseApplication::class)
class TestApplication : BaseApplication(), Application.ActivityLifecycleCallbacks {

  var currentActivity: FragmentActivity? = null

  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(this)
  }

  override fun onActivityPaused(p0: Activity) {}

  override fun onActivityResumed(activity: Activity) {
    if (activity is FragmentActivity) {
      currentActivity = activity
    }
  }

  override fun onActivityStarted(p0: Activity) {}

  override fun onActivityDestroyed(p0: Activity) {}

  override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {}

  override fun onActivityStopped(p0: Activity) {}

  override fun onActivityCreated(p0: Activity, p1: Bundle?) {}
}

open class BaseApplication : Application() {

  @Inject lateinit var workerFactory: HiltWorkerFactory

  override fun onCreate() {
    super.onCreate()
    MapsInitializer.initialize(applicationContext, MapsInitializer.Renderer.LATEST, null)
    initUrlManager()
    RxJavaPlugins.setErrorHandler(emptyConsumer())
    WorkManager.initialize(
        this, Configuration.Builder().setWorkerFactory(workerFactory).build())
    }
}

And I use this custom test runner to specify the TestApplication class should be used in instrumentation tests:我使用这个自定义测试运行程序来指定 TestApplication class 应该在仪器测试中使用:

class CustomTestRunner: AndroidJUnitRunner() {
    override fun newApplication(
        cl: ClassLoader,
        appName: String,
        context: Context
    ) : Application {
        return super.newApplication(
            cl, TestApplication::class.java.getName(), context)
    }
}

But when I try to run a test, I get the following error:但是当我尝试运行测试时,出现以下错误:

public final class TestApplication extends com.example.BaseApplication implements android.app.Application.ActivityLifecycleCallbacks { ^ @CustomTestApplication does not support application classes (or super classes) with @Inject fields. public final class TestApplication extends com.example.BaseApplication implements android.app.Application.ActivityLifecycleCallbacks { ^ @CustomTestApplication 不支持带有@Inject 字段的应用程序类(或超类)。 Found com.example.BaseApplication with @Inject fields [workerFactory].找到带有 @Inject 字段 [workerFactory] 的 com.example.BaseApplication。 [Hilt] Processing did not complete. [Hilt] 处理未完成。 See error above for details.有关详细信息,请参阅上面的错误。

If I do what the error suggests and get rid of the @Inject field in my BaseApplication class, then I can't set the work manager factory when the app starts so that's not going to work.如果我按照错误提示进行操作并删除我的 BaseApplication class 中的 @Inject 字段,那么我无法在应用程序启动时设置工作管理器工厂,这样就无法正常工作。

Is there a known workaround for this situation?这种情况有已知的解决方法吗? Is this issue I'm seeing due to some sort of architectural flaw where I just don't have my project setup correctly and could do away with initializing work manager in the application onCreate()?我看到的这个问题是由于某种体系结构缺陷导致的,我只是没有正确设置我的项目并且可以取消在应用程序 onCreate() 中初始化工作管理器吗?

You can use work-testing as mentioned in https://developer.android.com/topic/libraries/architecture/workmanager/how-to/integration-testing , then you have to inject workerFactory with HiltAndroidRule .您可以使用https://developer.android.com/topic/libraries/architecture/workmanager/how-to/integration-testing中提到的work-testing ,然后您必须使用HiltAndroidRule workerFactory

This worked for me:这对我有用:

@HiltAndroidTest
class MyInstrumentationTests() {

    @get:Rule
    private val hiltRule: HiltAndroidRule(this)
    
    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    @Before
    fun setUp() {
        hiltRule.inject() // has to be called first to initialize workerFactory

        val context = InstrumentationRegistry.getInstrumentation().targetContext
        val config = Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .setMinimumLoggingLevel(Log.DEBUG)
            .setExecutor(SynchronousExecutor())
            .build()

        // Initialize WorkManager for instrumentation tests.
        WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
    }
}

With that setup there is no need for BaseApplication , just create a runner as advised in https://developer.android.com/training/dependency-injection/hilt-testing#test-application使用该设置不需要BaseApplication ,只需按照https://developer.android.com/training/dependency-injection/hilt-testing#test-application中的建议创建一个跑步者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM