在Workmanager无效的情况下进行仪器测试

问题描述

当我尝试在包含WorkManager的应用程序中运行ActivityScenario时,在启动时出现以下错误

java.lang.IllegalStateException: WorkManager is not initialized properly.  You have explicitly disabled WorkManagerInitializer in your manifest,have not manually called WorkManager#initialize at this point,and your Application does not implement Configuration.Provider.

使用WorkManagerTestinitHelper工件中的work-test也无济于事。

WorkManager的定义如下:

@Provides
@Singleton
fun provideWorkmanager(@ApplicationContext context: Context) = WorkManager.getInstance(context)

这是我的测试atm:

    @HiltAndroidTest
    @RunWith(AndroidJUnit4::class)
    class LoginTest {
    
        @get:Rule(order = 0)
        var hiltRule = HiltAndroidRule(this)
    
        @get:Rule(order = 1)
        val activityRule = ActivityScenarioRule(MainActivity::class.java)
    
        @Before
        fun before() {
            val context = InstrumentationRegistry.getInstrumentation().targetContext
            val config = Configuration.Builder()
                .setMinimumLoggingLevel(Log.DEBUG)
                .setExecutor(SynchronousExecutor())
                .build()
            WorkManagerTestinitHelper.initializeTestWorkManager(context,config)
        }
    
        @Test
        fun test() {
            ...
        }

}

解决方法

这是因为根据Google Documentation@get:Rule@Before之前执行:

此规则提供对单个活动的功能测试。在使用@Test注释的每个测试之前以及在使用@Before注释的任何方法之前,将启动被测活动。在测试完成并且用@After注释的所有方法都完成之后,它终止。要在测试逻辑中访问被测活动,请提供一个可运行到ActivityScenarioRule.getScenario()。onActivity()的回调。

为解决此问题,您需要先在测试中使用WorkManager初始化WorkManagerTestInitHelper,然后再尝试启动活动。

为此,您应该避免使用ActivityScenarioRule,而应使用ActivityScenario,您可以执行以下操作:

@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class LoginTest {
    private lateinit var scenario: ActivityScenario<MainActivity>

    @get:Rule
    var hiltRule = HiltAndroidRule(this)

    @Before
    fun before() {
        val context = InstrumentationRegistry.getInstrumentation().targetContext
        val config = Configuration.Builder()
            .setMinimumLoggingLevel(Log.DEBUG)
            .setExecutor(SynchronousExecutor())
            .build()
        WorkManagerTestInitHelper.initializeTestWorkManager(context,config)

        scenario = launchActivity()
    }

    @Test
    fun test() {
        scenario.moveToState(Lifecycle.State.CREATED).onActivity { 
             activity -> // do some test with the activity
        }
    }
}
,

为了利用 ActivitScenarioRule 并确保首先初始化 WorkManager,我创建了一个自定义 JUnit 规则。

class WorkManagerRule : TestRule {
override fun apply(base: Statement?,description: Description?): Statement {
    return object : Statement() {
        override fun evaluate() {
            val context = InstrumentationRegistry.getInstrumentation().targetContext
            val config = Configuration.Builder()
                .setMinimumLoggingLevel(Log.DEBUG)
                .setExecutor(SynchronousExecutor())
                .build()
            WorkManagerTestInitHelper.initializeTestWorkManager(context,config)
            try {
                base?.evaluate()
            } finally {
                Log.d("WorkManagerRule","Do some teardown")
            }
        }

    }
}


@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class MyTest {
    @get:Rule(order = 0)
    var hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 1)
    var workMgrRule = WorkManagerRule()

    @get:Rule(order = 2)
    var activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Before
    fun init() {
        hiltRule.inject()
    }

    //Your test code here...
}

我使用了创建 JUnit 规则的说明,发现 here