0

I'm trying to test my koin modules following this koin documentation

import android.app.Application
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.SavedStateHandle
import io.mockk.mockkObject
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.koin.test.check.checkKoinModules
import org.koin.test.mock.MockProviderRule

class CheckModulesTest {

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

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

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

Note that my code is similar to the one on the documentation, but I'm using MockK, instead of Mockito.

Also, make sure to scroll down to also possible to use checkKoinModules on the link above to find the right snipet

However, I'm getting this error:

Failed to build object proxy
io.mockk.MockKException: Failed to build object proxy
    at app//io.mockk.impl.instantiation.JvmObjectMockFactory.objectMockk(JvmObjectMockFactory.kt:51)
    at app//com.sibela.smarthabits.di.CheckModulesTest$mockProvider$1.invoke(CheckModulesTest.kt:41)
    at app//com.sibela.smarthabits.di.CheckModulesTest$mockProvider$1.invoke(CheckModulesTest.kt:20)
    at app//com.sibela.smarthabits.di.CheckModulesTest$test DI modules$1.invoke(CheckModulesTest.kt:34)
    at app//com.sibela.smarthabits.di.CheckModulesTest$test DI modules$1.invoke(CheckModulesTest.kt:26)
    at app//org.koin.test.check.CheckModulesKt.declareParameterCreators(CheckModules.kt:110)
    at app//org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:102)
    at app//org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:40)
    at app//org.koin.test.check.CheckModulesKt.checkKoinModules(CheckModules.kt:65)
    at app//org.koin.test.check.CheckModulesKt.checkKoinModules$default(CheckModules.kt:62)
    at app//com.sibela.smarthabits.di.CheckModulesTest.test DI modules(CheckModulesTest.kt:26)
    at java.base@11.0.15/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base@11.0.15/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base@11.0.15/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base@11.0.15/java.lang.reflect.Method.invoke(Method.java:566)
    at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at app//org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at app//org.koin.test.mock.MockProviderRule$apply$1.evaluate(MockProviderRule.kt:28)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at java.base@11.0.15/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base@11.0.15/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base@11.0.15/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base@11.0.15/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: io.mockk.proxy.MockKAgentException: Failed to create proxy for class java.lang.Class.
class java.lang.Class is one of excluded classes
    at app//io.mockk.proxy.jvm.ProxyMaker.throwIfNotPossibleToProxy(ProxyMaker.kt:131)
    at app//io.mockk.proxy.jvm.ProxyMaker.proxy(ProxyMaker.kt:28)
    at app//io.mockk.impl.instantiation.JvmObjectMockFactory.objectMockk(JvmObjectMockFactory.kt:43)
    ... 55 more

My modules are very simple and here's a sumarized version of them:

import androidx.room.Room
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

private val daos = module {
    single {
        Room
            .databaseBuilder(
                androidContext(),
                FooDatabase::class.java,
                FooDatabase.DATABASE_NAME
            )
            .fallbackToDestructiveMigration()
            .build()
    }

    single { get<FooDatabase>().BarDao() }
    // other DAOs
}

private val repositories = module {
    single<FooRepository> { FooRepositoryImpl(get(), get()) }
    // other respositories
}

private val useCases = module {
    single { FooUseCase(get(), get(), get(), get()) }
    // other UseCases
}

private val viewModels = module {
    viewModel { FooViewModel(get(), get(), get()) }
    // other ViewModels
}

private val alarmSchedulers = module {
    single<FooAlarmScheduler> { FooAlarmSchedulerImpl(androidContext()) }
}

object AppModules {
    val modules = daos + repositories + useCases + mappers + viewModels + alarmSchedulers
}

Apart from the dependencies mentioned above, I only have a Repository that requires a Context:

class DataStoreRepositoryImpl(private val context: Context) : DataStoreRepository {

And some of my ViewModes require a SavedStateHandle:

class FooViewModel(
    private val savedStateHandle: SavedStateHandle,
    private val fooUseCase: FooUseCase,
    private val barUseCase: BarUseCase
) : ViewModel() {

I'm using the 3.3.0 version of Koin and the version 1.12.0 version of MockK:

def koin_version = '3.3.0'
implementation "io.insert-koin:koin-android:$koin_version"
testImplementation "io.insert-koin:koin-test-junit4:$koin_version"


testImplementation "io.mockk:mockk:1.12.0"
Leonardo Sibela
  • 1,613
  • 1
  • 18
  • 39
  • There seams to have an easier way to test a module, but I got some problems trying to use it (e.g. it does not find the SavedInstanceHadle dependency): https://insert-koin.io/docs/quickstart/android/#verifying-your-app – Leonardo Sibela Mar 15 '23 at 01:11

0 Answers0