Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WorkManager has error when testing with Robolectric

I'm using Android work manager with a custom initialization. to do that i disable auto-initialization in the manifest like this

        <provider
        tools:replace="android:authorities"
        android:name="androidx.work.impl.WorkManagerInitializer"
        android:authorities="${applicationId}.work_manager_init"
        android:enabled="false"
        android:exported="false" />

And in application code I use this code

private fun initWorkManager() {
    WorkManager.initialize(this, Configuration.Builder().run {
        setWorkerFactory(appComponent.daggerWorkerFactory())
        build()
    })
}

And it works fine when I run my application. But when I'm testing with roboletric any class that needs the context by RuntimeEnvironment.application throws this exception

java.lang.IllegalStateException: WorkManager is already initialized.  
Did you try to initialize it manually without disabling 
WorkManagerInitializer? See WorkManager#initialize(Context, 
Configuration) or the class levelJavadoc for more information.

The initWorkManager() get calls and throw this beacuse it doesn't know auto-init is already disabled in the manifest and somehow my test cannot read the values from the manifest file.

Any help or suggestion will be appritiated.

like image 480
Alireza A. Ahmadi Avatar asked Jan 08 '19 07:01

Alireza A. Ahmadi


People also ask

How can I tell if WorkManager is running on Android?

You can check this by running getStatus() method on the WorkInfo instance. Calling the state immediately after enqueuing the WorkRequest will give the state as ENQUEUED and hence don't get any output data.

How do you test a CoroutineWorker?

To test a ListenableWorker or its variants ( CoroutineWorker and RxWorker ), use TestListenableWorkerBuilder .

What is difference between WorkManager and service?

WorkManager is not answer to all of the background tasks. E.G. You shouldn't use it for processing payments since it doesn't need to survive process death and these task needs to be executed immediately. Consider using Foreground Service. Its also not a great idea to use them for parsing data and contents of view.


1 Answers

I solved a similar issue with the help of the Androidx Work Manager testing utils. For reference see the docs here: Android work manager testing docs

Basically what you need to do is add a dependency to include the work manger test utils:

testImplementation 'androidx.work:work-testing:2.0.1'

Then you will be able to call code in your test setup similar to this:

final Configuration config = new Configuration.Builder()
    .setMinimumLoggingLevel(Log.DEBUG)
    .setExecutor(new SynchronousExecutor())
    .build();
WorkManagerTestInitHelper.initializeTestWorkManager(
    context, config);

Whereas the context could obtained in different ways, depending on your test infrastructure.

With this approach no other steps like excluding something from the manifest are necessary.

like image 167
Christian.D Avatar answered Nov 15 '22 06:11

Christian.D