InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
9.08k stars 718 forks source link

koin-androidx-workmanager: checkKoinModules failes with ClassCastException with using workManagerFactory() #1406

Closed bigman212 closed 1 year ago

bigman212 commented 2 years ago

Describe the bug When defining worker { } block in module and try to unit test the dependency graph - the unit tests fails.

To Reproduce Steps to reproduce the behavior:

  1. Define a simple worker:
    
    // TransactionWorker.kt
    class TransactionWorker(
    context: Context,
    workerParams: WorkerParameters,
    ) : CoroutineWorker(context, workerParams), KoinComponent {
    override suspend fun doWork(): Result {
        return Result.success()
    }
    }
    // AppModule.kt
    object AppModule {
    val module = module {
        worker { TransactionWorker(androidContext(), get()) }
        }
    }
    }

// App.kt - onCreate startKoin { androidContext(this@App) workManagerFactory() modules(AppModule.module) }


2. Write a dependency graph unit test:
```kotlin
    @Test
    fun verifyKoinApp() {
        checkKoinModules(
            modules = listOf(AppModule.module),
            appDeclaration = {
                androidContext(mockk(relaxed = true))
                workManagerFactory()
            }
        )
    }
  1. Unit test fails:
    class java.lang.Object cannot be cast to class android.net.ConnectivityManager (java.lang.Object is in module java.base of loader 'bootstrap'; android.net.ConnectivityManager is in unnamed module of loader 'app')
    java.lang.ClassCastException: class java.lang.Object cannot be cast to class android.net.ConnectivityManager (java.lang.Object is in module java.base of loader 'bootstrap'; android.net.ConnectivityManager is in unnamed module of loader 'app')
    at androidx.work.impl.constraints.trackers.NetworkStateTracker.<init>(NetworkStateTracker.java:71)
    at androidx.work.impl.constraints.trackers.Trackers.<init>(Trackers.java:65)
    at androidx.work.impl.constraints.trackers.Trackers.getInstance(Trackers.java:43)
    at androidx.work.impl.constraints.controllers.BatteryChargingController.<init>(BatteryChargingController.java:31)
    at androidx.work.impl.constraints.WorkConstraintsTracker.<init>(WorkConstraintsTracker.java:71)
    at androidx.work.impl.background.greedy.GreedyScheduler.<init>(GreedyScheduler.java:73)
    at androidx.work.impl.WorkManagerImpl.createSchedulers(WorkManagerImpl.java:786)
    at androidx.work.impl.WorkManagerImpl.<init>(WorkManagerImpl.java:270)
    at androidx.work.impl.WorkManagerImpl.<init>(WorkManagerImpl.java:241)
    at androidx.work.impl.WorkManagerImpl.<init>(WorkManagerImpl.java:219)
    at androidx.work.impl.WorkManagerImpl.initialize(WorkManagerImpl.java:198)
    at androidx.work.WorkManager.initialize(WorkManager.java:210)
    at org.koin.androidx.workmanager.koin.KoinApplicationExtKt.createWorkManagerFactory(KoinApplicationExt.kt:43)
    at org.koin.androidx.workmanager.koin.KoinApplicationExtKt.workManagerFactory(KoinApplicationExt.kt:30)
    at com.example.CheckModulesTest$verifyKoinApp$1.invoke(CheckKoinTest.kt:68)

    I couldn't find a way to mock ConnectivityManager properly.

Expected behavior Unit test passes, worker is created.

Koin project used and used version (please complete the following information):

    def koinVersion = '3.2.0'
    implementation "io.insert-koin:koin-android:$koinVersion"
    implementation "io.insert-koin:koin-androidx-workmanager:$koinVersion"
    testImplementation "io.insert-koin:koin-test:$koinVersion"
    testImplementation "io.insert-koin:koin-test-junit4:$koinVersion"
    def work_version = "2.7.1"
    implementation "androidx.work:work-runtime-ktx:$work_version"
    androidTestImplementation "androidx.work:work-testing:$work_version"

Additional moduleDefinition No info.

arnaudgiuliani commented 1 year ago

Hello, I've just proposed a new JVM API to let you verify your app configuration: Module.verify()

https://github.com/InsertKoinIO/koin/blob/core/3.3.0/core/koin-test/src/jvmMain/kotlin/org/koin/test/verify/VerifyModule.kt#L22

this will analyze your class constructors against your Koin configuration. No need of mocking, just call verify() on your module.

For any "extra types" (such as Context, SavedStateHandle, WorkParamaters), you can declare them with extraTypes parameter.