【问题标题】:KoinAppAlreadyStartedException: A Koin Application has already been startedKoinAppAlreadyStartedException:一个 Koin 应用程序已经启动
【发布时间】:2019-11-24 02:28:53
【问题描述】:

使用 koin-2.0.1 进行 Android 测试,虽然每个测试都单独通过,但无法同时测试所有 3 个测试。

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)
    }
}

运行类级别测试结果如下:

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

任何意见都会有所帮助,谢谢。

【问题讨论】:

    标签: testing kotlin koin


    【解决方案1】:

    一种常见的做法是将@Before setup 与@After cleanup 配对。您可以在那里拨打stopKoin(),以便下次拨打startKoin() 可以再次使用:

    @After
    fun tearDown() {
        stopKoin()
    }
    

    【讨论】:

    • 或者,@BeforeClass/@AfterClass
    • 扩展 AutoCloseKoinTest 是一种更直接和简洁的方法,因为您不需要手动编写 @After 设置来停止 koin
    • 对我不起作用,必须这样做if (KoinContextHandler.getOrNull() == null) { startKoin...
    【解决方案2】:

    作为@After 方法的替代方法,您还可以使用AutoCloseKoinTestAs described in the docs:

    扩展 Koin 测试 - 嵌入 autoclose @after 方法以在每次测试后关闭 Koin

    您可以扩展AutoCloseKoinTest,而不是扩展KoinTest,它会为您完成后续测试。

    【讨论】:

    【解决方案3】:

    在@Before 和@After 方法上调用 stopKoin(),如下所示:

    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)
        }
    }
    

    【讨论】:

      【解决方案4】:

      解决此问题的另一种方法是在您启动 Koin 的应用程序中覆盖 onTerminate

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

      通过这种方式,您将不必使用AutoCloseKoinTest 或在@after 中的每个类测试中关闭它

      【讨论】:

        【解决方案5】:

        实现抽象 AutoCloseKoinTest 类将在每次测试后自动停止 Koin。

        以下是 Robolectric 的示例:

        @RunWith(RoboelectricTestRunner::class)
        class MyTest : AutoCloseKoinTest() {
           private val appContext = ApplicationProvider.getApplicationContext<APPNAME>()
        
           @Before
           fun setup() {
              // use appContext as needed
           }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-01
          • 2017-01-02
          • 2014-10-31
          • 1970-01-01
          • 2010-10-15
          • 2015-03-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多