KoinAppAlreadyStartedException:Koin 应用程序已经启动
KoinAppAlreadyStartedException: A Koin Application has already been started
使用 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)
}
}
运行 class 水平测试结果如下:
org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started
任何意见都会有所帮助,谢谢。
常见的做法是将 @Before
设置与 @After
清理配对。您可以在那里调用 stopKoin()
,以便下一次调用 startKoin()
再次工作:
@After
fun tearDown() {
stopKoin()
}
作为 @After
方法的替代方法,您还可以使用 AutoCloseKoinTest
。 As described in the docs:
Extended Koin Test - embed autoclose @after method to close Koin after every test
您可以扩展 AutoCloseKoinTest
而不是扩展 KoinTest
,它将为您进行后续测试。
解决此问题的另一种方法是在您启动 Koin
的应用程序中覆盖 onTerminate
override fun onTerminate() {
super.onTerminate()
stopKoin()
}
通过这种方式,您将不必在 @after
的每个 class 测试中使用 AutoCloseKoinTest
或关闭它
在@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)
}
}
实施抽象 AutoCloseKoinTest class 将在每次测试后自动停止 Koin。
这里有一个 Robolectric 的例子:
@RunWith(RoboelectricTestRunner::class)
class MyTest : AutoCloseKoinTest() {
private val appContext = ApplicationProvider.getApplicationContext<APPNAME>()
@Before
fun setup() {
// use appContext as needed
}
}
使用 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)
}
}
运行 class 水平测试结果如下:
org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started
任何意见都会有所帮助,谢谢。
常见的做法是将 @Before
设置与 @After
清理配对。您可以在那里调用 stopKoin()
,以便下一次调用 startKoin()
再次工作:
@After
fun tearDown() {
stopKoin()
}
作为 @After
方法的替代方法,您还可以使用 AutoCloseKoinTest
。 As described in the docs:
Extended Koin Test - embed autoclose @after method to close Koin after every test
您可以扩展 AutoCloseKoinTest
而不是扩展 KoinTest
,它将为您进行后续测试。
解决此问题的另一种方法是在您启动 Koin
的应用程序中覆盖onTerminate
override fun onTerminate() {
super.onTerminate()
stopKoin()
}
通过这种方式,您将不必在 @after
AutoCloseKoinTest
或关闭它
在@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)
}
}
实施抽象 AutoCloseKoinTest class 将在每次测试后自动停止 Koin。
这里有一个 Robolectric 的例子:
@RunWith(RoboelectricTestRunner::class)
class MyTest : AutoCloseKoinTest() {
private val appContext = ApplicationProvider.getApplicationContext<APPNAME>()
@Before
fun setup() {
// use appContext as needed
}
}