Koin: ViewModels, Scopes & Testing
ViewModel Injection on Android
val appModule = module {
viewModel { ProfileViewModel(get()) }
}
class ProfileFragment : Fragment() {
private val viewModel: ProfileViewModel by viewModel()
// Koin integrates with the Jetpack ViewModel lifecycle
}Qualifiers for Multiple Bindings of the Same Type
val networkModule = module {
single(named("authClient")) { ApiClient(baseUrl = AUTH_URL) }
single(named("dataClient")) { ApiClient(baseUrl = DATA_URL) }
}
val authClient: ApiClient by inject(named("authClient"))Binding to an Interface
single<UserRepository> { UserRepositoryImpl(get()) } bind UserRepository::class
// Consumers can depend on the UserRepository abstraction
// rather than the concrete UserRepositoryImpl classTesting With a Mock Module
class UserRepositoryTest : KoinTest {
@Before
fun setup() {
startKoin {
modules(module {
single<ApiClient> { mockk(relaxed = true) }
single { UserRepository(get()) }
})
}
}
}
// A test-specific module swaps in mocks for the same types,
// isolating the class under test from real dependenciesVerifying the Graph Early
Because Koin resolves lazily by default, a broken definition might not surface until a specific code path actually runs. Koin's checkModules() (typically run as a test) proactively verifies the whole dependency graph resolves correctly, catching misconfigurations earlier than waiting for a runtime crash.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free