Seems like there’s breaking changes to `checkModul...
# koin
r
Seems like there’s breaking changes to
checkModules()
in 3.1.0. Nothing in the changelog about it. What’s the story there? I’m having trouble understanding how to migrate my tests from the lambda-based setup I had before.
I used to be doing this, essentially:
Copy code
try {
    val koinApplication = startKoin { ... }

    koinApplication.koin.checkModules {
        koin.createScope(testScopeId, koinUiScopeQualifier)
        create<LocationDetailViewModel> { parametersOf(1L) }
    }
} finally {
    stopKoin()
}
I have a custom scope in my koin configuration, so I needed the
createScope()
call in the test to mimic what the prod code was doing.
But now the
checkModules()
that takes a lambda is gone. So I’m trying something like this
Copy code
try {
    val koinApplication = startKoin { ... }

    koinApplication.koin.createScope(testScopeId, koinUiScopeQualifier)
    koinApplication.checkModules(mapOf(Long::class to 1L))
} finally {
    stopKoin()
}
This gives me
java.lang.IllegalStateException: Missing MockProvider
, which I think means I’m not wiring something up correctly because I’m not using mocks in my tests, so I assume the error is just because it can’t find something it’s looking for.
j
@russhwolf I had run in to exact same issue and had intended to get back to it again....but completely forgot! fwiw I just made following updates based on sample that's in Koin repo....not sure if there's different/better way but seemed like that
MockProviderRule
is needed now... https://github.com/joreilly/PeopleInSpace/commit/57e2eea1cba8538602f4d28ac55c8c3a2f9084bf
r
That only works for JVM though
j
ah, good point
I have that test in my
app
module right now....but probably should have it in common code....
r
yeah I 100% want to be testing my native modules too
they’re not always the same as JVM
Here’s a minimal sample of a test that fails looking for a MockProvider. That graph shouldn’t need to mock anything, and it’s actually impossible to interact with MockProvider from native anyway because it includes mutable state in a top-level object which leads to an
InvalidMutabilityException
when you call
register()
.
Copy code
class Box(val contents: String)

class KoinModulesTest {
    @Test
    fun checkModulesTest() {
        val koinApplication = startKoin {
            modules(module {
                single { "foo" }
                single { Box(get()) }
            })
        }

        koinApplication.checkModules()
    }

    @AfterTest
    fun tearDown() {
        stopKoin()
    }
}
a
Yes
checkModules
is simplified, following the new internals
yes, missed to add to it to changelog 👍
thanks for your feedback
I’ve tried to propose something to avoid create values. The idea is to mock definitions that have passed, a kindof sandbox execution.
Copy code
/**
 * Check all definition's dependencies - start all modules and check if definitions can run
 */
fun KoinApplication.checkModules(
    defaultValues: Map<KClass<*>, Any> = hashMapOf(),
    allowedMocks: List<KClass<*>> = listOf(),
    allowedExceptions: List<KClass<*>> = listOf()
) = koin.checkModules(defaultValues, allowedMocks, allowedExceptions)
like this usage:
Copy code
checkModules(
    allowedMocks = listOf(
        WorkerParameters::class,
        SavedStateHandle::class
    ),
    allowedExceptions = listOf(
        NullPointerException::class
    )
){
    androidContext(MockProvider.makeMock<Application>())
    modules(allModules)
}
r
What does usage look like if I don't want mocks? I don't see any way to avoid the internal calls into
MockProvider
a
let me revert to old API, was not a good idea for such breakings 😕
👍 1