Search code examples
junitkotlindependency-injectionstatickoin

How can I use Koin to inject in a @BeforeClass static method?


I have an integration test that needs to call a REST service to get an access token one time before any subsequent tests are run. Before adding Koin to my project, I accomplished this in a static method annotated with @BeforeClass like so:

class PersonRepositoryIntegrationTest {

    companion object {
        private var _clientToken: String? = null

        @BeforeClass
        @JvmStatic
        fun setup() {
            _clientToken = AuthRepository().getClientToken()!!.accessToken
        }
    }

    @Test
    fun testCreatePerson() {
        PersonRepository().createPerson(_clientToken)
    }

AuthRepository and PersonRepository have additional dependencies that up until now were instantiated in their constructors. Now, I want to use Koin to resolve these dependencies by injecting the repositories:

class PersonRepositoryIntegrationTest : KoinTest {

    companion object {
        private val _authRepository by inject<IAuthRepository>()
        private val _personRepository by inject<IPersonRepository>()
        private var _clientToken: String? = null

        @BeforeClass
        @JvmStatic
        fun beforeClass() {
            startKoin(listOf(AppModule.appModule))
            _clientToken = _authRepository.getClientToken()!!.accessToken
        }
    }

When I try to use inject inside the companion object, the compiler gives an error:

Unresolved reference.
None of the following candidates is applicable because of receiver type mismatch.

* public inline fun <reified T : Any> KoinComponent.inject(name: String = ..., scope: Scope? = ..., noinline parameters: ParameterDefinition = ...): Lazy<IAuthRepository> defined in org.koin.standalone

Is there another way I can use Koin to inject my classes in a @BeforeClass static method like this?


Solution

  • According to kotlin documentation, companion objects are technically real objects.

    even though the members of companion objects look like static members in other languages, at runtime those are still instance members of real objects, and can, for example, implement interfaces:

    If a class wants to inject dependencies and it is not one of the koin supported classes(Activity, Fragment, ViewModel, KoinTest etc), then that class should implement the KoinComponent interface.

    So consider changing your companion object definition to the following and try again.

    companion object : KoinComponent{
            private val _authRepository by inject<IAuthRepository>()
            private val _personRepository by inject<IPersonRepository>()
            private var _clientToken: String? = null
    
            @BeforeClass
            @JvmStatic
            fun beforeClass() {
                startKoin(listOf(AppModule.appModule))
                _clientToken = _authRepository.getClientToken()!!.accessToken
            }