Koin
02 / 02

Koin: ViewModels, Scopes & Testing

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 class

Testing 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 dependencies

Verifying 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