How can I test Android WorkManager with setRequiredNetworkType(NetworkType.CONNECTED) constraint?
Asked Answered
A

1

6

I am trying to write Android instrumentation tests for a class that contains WorkManager WorkRequests.

For a long time I was stuck at the point where I could see the workers being enqueued but they never got executed. After some time and trial and error I realised the following constraint was blocking the test:

...
 setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
...

If I remove that constraint the work item is executed as expected.

My virtual device has a network connection so not sure why this constraint isn't being met in my test.

Does anyone have any advice on how to fix this as I need to write tests that cover cases where this constraint is met and when it isn't.

My work request is pretty simple but here it is:

val workRequest = OneTimeWorkRequestBuilder<T>()
                .addTag(syncWork.getSyncType().name)
                .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
                .build()

syncWorkRepository.save(syncWork.apply { id = workRequest.id.toString() })

workManager.enqueue(workRequest)

I have tried:

val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
    wifi.isWifiEnabled = true

but this throws a Security exception:

SecurityException: WifiService: Neither user 10139 nor current process has android.permission.CHANGE_WIFI_STATE.

I have also added code to my test to check network state:

val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
    val isConnected: Boolean = activeNetwork?.isConnected == true

And isConnected is true but still the WorkManager constraint is not met and so the work is not executed.

Also tried:

val testDriver = getTestDriver()

with

testDriver?.setAllConstraintsMet(workInfo.id)

inside my observe LiveData by tag method which I can see being executed once for the ENQUEUED state.

Here is my observer in the test:

syncManager.syncWork(SyncType.ALL)
        .observe(lifecycleOwner, Observer { listOfWorkInfo ->
        listOfWorkInfo.forEach { workInfo ->
            Log.d("TAG", "${workInfo.id}")
            testDriver?.setAllConstraintsMet(workInfo.id)
            if(workInfo.state == WorkInfo.State.SUCCEEDED) {
                Log.d("TAG", workInfo.state.name)
                latch.countDown()
            } else if(workInfo.state != WorkInfo.State.ENQUEUED) {
                Log.d("TAG", workInfo.state.name)
                latch.countDown()
            }
        }
    })

Thanks, Paul

Alphaalphabet answered 31/1, 2019 at 10:58 Comment(0)
S
0

You should be using WorkManagerTestInitHelper. Once you use the TestDriver and mark your constraint as met, your Worker should execute.

Supererogate answered 28/5, 2019 at 21:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.