Skip to main content
Version: 4.2 - LTS

Verifying your Koin configuration

Koin allows you to verify your configuration modules, avoiding discovering dependency injection issues at runtime.

Compile-Time Safety Now Available

The Koin Compiler Plugin now provides compile-time dependency validation — catching missing dependencies, qualifier mismatches, and broken call sites at build time. This replaces the need for verify() and checkModules() in most cases.

See Compile-Time Safety to migrate.

Verify API - JVM Only [3.3+]​

Use the verify() extension function on a Koin Module. Under the hood, this will verify all constructor classes and crosscheck with the Koin configuration to know if there is a component declared for this dependency. In case of failure, the function will throw a MissingKoinDefinitionException.

val niaAppModule = module {
includes(
jankStatsKoinModule,
dataKoinModule,
syncWorkerKoinModule,
topicKoinModule,
authorKoinModule,
interestsKoinModule,
settingsKoinModule,
bookMarksKoinModule,
forYouKoinModule
)
viewModel<MainActivityViewModel>()
}
class NiaAppModuleCheck {

@Test
fun checkKoinModule() {
// Verify Koin configuration
niaAppModule.verify()
}
}

Launch the JUnit test and you're done!

The verify() API is ultra light to run and doesn't require any kind of mock/stub to run on your configuration.

Verifying with Injected Parameters [4.0+]​

When you have a configuration that implies injected objects with parametersOf, the verification will fail because there is no definition of the parameter's type in your configuration. However you can define a parameter type, to be injected with given definition definition<Type>(Class1::class, Class2::class ...).

class ModuleCheck {

// given a definition with an injected definition
val module = module {
single { (a: Simple.ComponentA) -> Simple.ComponentB(a) }
}

@Test
fun checkKoinModule() {

// Verify and declare Injected Parameters
module.verify(
injections = injectedParameters(
definition<Simple.ComponentB>(Simple.ComponentA::class)
)
)
}
}

Type White-Listing​

We can add types as "white-listed". This means that this type is considered as present in the system for any definition:

class NiaAppModuleCheck {

@Test
fun checkKoinModule() {

// Verify Koin configuration
niaAppModule.verify(
// List types used in definitions but not declared directly (like parameter injection)
extraTypes = listOf(MyType::class ...)
)
}
}

Using Annotations for Verification​

Annotations from koin-core-annotations help Koin infer injection contracts and validate configurations. Instead of having a complex DSL configuration, this helps identify those elements:

// indicates that "a" is an injected parameter
class ComponentB(@InjectedParam val a: ComponentA)
// indicates that "a" is dynamically provided
class ComponentBProvided(@Provided val a: ComponentA)

This helps prevent subtle issues during testing or runtime without writing custom verification logic.


CheckModules API (Deprecated)​

warning

The checkModules() API is deprecated since Koin 4.0. Use verify() instead, or migrate to the Koin Compiler Plugin for compile-time safety.

The checkModules() function launches your modules and tries to run each possible definition.

class CheckModulesTest : KoinTest {

@Test
fun verifyKoinApp() {

koinApplication {
modules(module1, module2)
checkModules()
}
}
}

Or using checkKoinModules:

class CheckModulesTest : KoinTest {

@Test
fun verifyKoinApp() {
checkKoinModules(listOf(module1, module2))
}
}

CheckModule DSL​

For any definition using injected parameters, properties or dynamic instances:

  • withInstance(value) - will add value instance to Koin graph
  • withInstance<MyType>() - will add a mocked instance of MyType (requires MockProviderRule)
  • withParameter<Type>(qualifier){ qualifier -> value } - will add value instance to be injected as parameter
  • withProperty(key, value) - add property to Koin

Mocking with a JUnit Rule​

To use mocks with checkModules, provide a MockProviderRule:

@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
// Mock with your framework here given clazz
Mockito.mock(clazz.java)
}

Verifying Modules with Dynamic Behavior​

val myModule = module {
factory { (id: String) -> FactoryPresenter(id) }
}

Verify with:

class CheckModulesTest : KoinTest {

@Test
fun verifyKoinApp() {

koinApplication {
modules(myModule)
checkModules(){
// value to add to Koin, used by definition
withInstance("_my_id_value")
}
}
}
}

Android Example​

class CheckModulesTest {

@get:Rule
val rule: TestRule = InstantTaskExecutorRule()

@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
Mockito.mock(clazz.java)
}

@Test
fun `test DI modules`(){
checkKoinModules(allModules) {
withInstance<Context>()
withInstance<Application>()
withInstance<SavedStateHandle>()
withInstance<WorkerParameters>()
}
}
}

Link scopes using withScopeLink:

val myModule = module {
scope(named("scope1")) {
scoped { ComponentA() }
}
scope(named("scope2")) {
scoped { ComponentB(get()) }
}
}

@Test
fun `test DI modules`(){
koinApplication {
modules(myModule)
checkModules(){
withScopeLink(named("scope2"), named("scope1"))
}
}
}

Migration to Compile-Time Safety​

The Koin Compiler Plugin now provides compile-time dependency validation, replacing the need for runtime verification:

BeforeAfter
module.verify() in testCompiler Plugin (automatic)
checkModules() in testCompiler Plugin (automatic)
Runtime verificationCompile-time verification
Manual test setupNo test code needed

The compiler validates on every build — no test code required. You can safely remove your verify() and checkModules() tests after enabling the compiler plugin.

See Compile-Time Safety for full details and Compiler Plugin Setup for setup instructions.