Reputation: 1529
When I try to run an ActivityScenario in my application that contains a WorkManager I get the following error on start:
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.
Using the WorkManagerTestInitHelper
from the work-test
artifact doesnt help either.
The WorkManager is defined like this:
@Provides
@Singleton
fun provideWorkmanager(@ApplicationContext context: Context) = WorkManager.getInstance(context)
This is my test 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() {
...
}
}
Upvotes: 6
Views: 1676
Reputation: 1125
To take advantage of ActivitScenarioRule
and ensure that the WorkManager
is initialized first I created a custom JUnit rule.
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...
}
I used the instructions for creating JUnit rules found here.
Upvotes: 4
Reputation: 440
This is because @get:Rule
executes before the @Before
does, as per the Google Documentation:
This rule provides functional testing of a single activity. The activity under test is launched before each test annotated with @Test and before any method annotated with @Before. It's terminated after the test is completed and all methods annotated with @After are finished. To access the activity under test in your test logic, provide a callback runnable to ActivityScenarioRule.getScenario().onActivity().
In order to fix this, you would need to initialise the WorkManager
in the test with WorkManagerTestInitHelper
before you try to launch the activity.
To do this, you should avoid using ActivityScenarioRule
and use ActivityScenario
instead, you can do something like this:
@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
}
}
}
Upvotes: 3