KoinAppAlreadyStartedException: A Koin Application has already been started

时光怂恿深爱的人放手 提交于 2020-12-08 10:51:28

问题


Using koin-2.0.1 for Android testing and unable to test all 3 test together though each test passes separately.

class NumberFormatterUtilImplTest : KoinTest {

    private val numberFormatterUtil: NumberFormatterUtilImpl by inject()

    @Before
    fun setUp() {
        startKoin { modules(utilsModule) }
    }

    @Test
    fun `does formatter returns two digit faction if supplied one digit value`() {
        val result = numberFormatterUtil.getAdjustedCurrencyRate(18.0)
        Assert.assertEquals(result, 18.00, 1.0)
    }

    @Test
    fun `does formatter returns two digit faction if supplied multiple digits value`() {
        val result = numberFormatterUtil.getAdjustedCurrencyRate(18.12343)
        Assert.assertEquals(result, 18.12, 1.0)
    }

    @Test
    fun `does formatter returns rounded two digit faction if supplied multiple digits value`() {
        val result = numberFormatterUtil.getAdjustedCurrencyRate(18.12876)
        Assert.assertEquals(result, 18.13, 1.0)
    }
}

running class level testing resulting below:

org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started

any input would be helpful, thanks.


回答1:


As an alternative to the @After approach, you can also use AutoCloseKoinTest. As described in the docs:

Extended Koin Test - embed autoclose @after method to close Koin after every test

Instead of extending KoinTest, you can extend AutoCloseKoinTest and it will do the after test for you.




回答2:


A common practice is to pair @Before setup with @After cleanup. You can call stopKoin() there so the next call to startKoin() works again:

@After
fun tearDown() {
    stopKoin()
}



回答3:


Another way to resolve this it override onTerminate in your application where you start Koin

override fun onTerminate() {
    super.onTerminate()     
    stopKoin()              
}

With this way you will not have to use AutoCloseKoinTest or close it in every class test in the @after




回答4:


Call stopKoin() on @Before and @After method like below:

import com.my.example.appModule
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.test.KoinTest
import org.koin.test.inject
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import java.util.*

@Config(sdk = [Build.VERSION_CODES.LOLLIPOP])
@RunWith(RobolectricTestRunner::class)
class SomeRepositoryTest: KoinTest {

    // Return Completable of RxJava
    private val repository: SomeRepository by inject()

    @Before
    fun before() {
        stopKoin() // to remove 'A Koin Application has already been started'
        startKoin {
            androidContext(ApplicationProvider.getApplicationContext())
            modules(appModule)
        }
    }

    @After
    fun after() {
        stopKoin()
    }

    @Test
    fun testSomething() {

        repository.insert("data").blockingAwait()

        assert(true)
    }
}



回答5:


Implementing the abstract AutoCloseKoinTest class will automatically stop Koin after each test.

Here's an example with Robolectric:

@RunWith(RoboelectricTestRunner::class)
class MyTest : AutoCloseKoinTest() {
   private val appContext = ApplicationProvider.getApplicationContext<APPNAME>()

   @Before
   fun setup() {
      // use appContext as needed
   }
}


来源:https://stackoverflow.com/questions/57038848/koinappalreadystartedexception-a-koin-application-has-already-been-started

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!