Skip to main content
Version: 4.2

JUnit Tests

This tutorial lets you test a Kotlin application and use Koin inject and retrieve your components.

note

update - 2025-01-28

Get the code

Gradle Setup

First, add the Koin dependency like below:

dependencies {
// Koin testing tools
testImplementation "io.insert-koin:koin-test:$koin_version"
// Needed JUnit version
testImplementation "io.insert-koin:koin-test-junit4:$koin_version"
}

Declared dependencies

We reuse the koin-core getting-started project, to use the koin module:

val appModule = module {
single<UserApplication>()
single<UserRepositoryImpl>() bind UserRepository::class
single<UserServiceImpl>() bind UserService::class
}

Verifying your Modules

tip

The Koin Compiler Plugin now provides compile-time dependency validation, catching missing dependencies at build time without writing test code. See Compile-Time Safety.

If you're not using the compiler plugin, you can verify modules at runtime. The verify() function performs a dry-run check to ensure all dependencies can be resolved:

class ModuleVerificationTest : AutoCloseKoinTest() {

@Test
fun verifyModules() {
appModule.verify()
}
}

This test will fail if any dependency definitions are invalid or if any required dependencies are missing.

Writing Tests with KoinTestRule

To write tests that inject dependencies, extend KoinTest and use KoinTestRule:

class UserAppTest : KoinTest {

val userService by inject<UserService>()
val userRepository by inject<UserRepository>()

@get:Rule
val koinTestRule = KoinTestRule.create {
printLogger()
modules(appModule)
}

@Test
fun `test user service`() {
// Load users via service
userService.loadUsers()

// Verify user can be found
val user = userService.getUserOrNull("Alice")
assertNotNull(user)
assertEquals("Alice", user?.name)
}
}

We use the KoinTestRule to start/stop our Koin context for each test

Mocking Dependencies

You can mock dependencies in your tests using declareMock. This replaces the real implementation with a mock:

class UserMockTest : KoinTest {

@get:Rule
val koinTestRule = KoinTestRule.create {
printLogger(Level.DEBUG)
modules(appModule)
}

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

@Test
fun `mock test`() {
// Declare a mock for UserRepository
val repository = declareMock<UserRepository> {
given(findUserOrNull(anyString())).willReturn(
User("Mock", "mock@example.com")
)
}

// Use the application with mocked repository
getKoin().get<UserApplication>().sayHello("Mock")

// Verify the mock was called
Mockito.verify(repository, times(1)).findUserOrNull(anyString())
}
}

The MockProviderRule configures Mockito as the mocking framework, and declareMock replaces the real UserRepository with a mock that returns controlled data.

Key Testing Concepts

ConceptDescription
KoinTestInterface to extend for Koin testing support
AutoCloseKoinTestAuto-closes Koin after each test
KoinTestRuleJUnit rule to start/stop Koin context
MockProviderRuleConfigures the mocking framework
verify()Validates module configuration without running
declareMock<T>()Replaces a definition with a mock
by inject<T>()Lazily injects a dependency in tests

See Also