我试图在androidtest文件夹下使用
Koin creator's example
. 如果我一个一个地运行它们,每个测试都会通过。但当我一次跑完所有的时候,只有第一次传球。其余失败的原因是:
BeanInstanceCreationException: Can't create definition for 'Single [name='MovieDatabase',...
. 以下是我的测试:
class MovieDatabaseTest: AutoCloseKoinTest() {
@get:Rule val instantExecutorRule = InstantTaskExecutorRule()
private val movieDatabase: MovieDatabase by inject()
private val movieDAO: DetailDao by inject()
private val testModule = module {
single(override = true) {
Room.inMemoryDatabaseBuilder(androidContext (), MovieDatabase::class.java)
.allowMainThreadQueries()
.build()
}
}
@Before fun setUp() {
loadKoinModules(testModule)
}
@After fun tearDown() {
movieDatabase.close()
}
@Test
fun saveMovieTest() {
val observer = mock<Observer<Movie>>()
val date = Date()
val movie = buildMovie(1, dateUpdate = date)
val captor = ArgumentCaptor.forClass(Movie::class.java)
movieDAO.saveMovie(movie)
val movieLD = movieDAO.getMovie(1)
movieLD.observeForever(observer)
verify(observer).onChanged(captor.capture())
assertEquals(captor.value, buildMovie(1, dateUpdate = date))
}
@Test
fun likeTest() {
val movie = buildMovie(1)
movieDAO.saveMovie(movie)
movieDAO.like(1, true)
val movieLD = movieDAO.getMovie(1)
movieLD.observeForever {
assert(it.liked)
}
}
@Test
fun getMovieByDateTest() {
val dateUpdate = Date()
val queryDate = Date(System.currentTimeMillis() - 3600 * 1000)
val movie = buildMovie(1, dateUpdate = dateUpdate)
movieDAO.saveMovie(movie)
val savedMovie = movieDAO.getMovieByDate(1, queryDate)
assertNotNull(savedMovie)
}
}
错误堆栈跟踪:
org.koin.error.BeanInstanceCreationException: Can't create definition for 'Single [name='MovieDatabase',class='us.kostenko.architecturecomponentstmdb.common.database.MovieDatabase']' due to error :
No compatible definition found. Check your module definition
org.koin.core.bean.BeanRegistry.checkedResult(BeanRegistry.kt:120)
org.koin.core.bean.BeanRegistry.retrieveDefinition(BeanRegistry.kt:87)
org.koin.core.instance.InstanceRegistry.findDefinition(InstanceRegistry.kt:125)
org.koin.core.instance.InstanceRegistry.access$findDefinition(InstanceRegistry.kt:39)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$1.invoke(InstanceRegistry.kt:91)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$1.invoke(InstanceRegistry.kt:39)
org.koin.core.time.DurationKt.logDuration(Duration.kt:11)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:90)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:39)
org.koin.core.time.DurationKt.measureDuration(Duration.kt:19)
org.koin.core.instance.InstanceRegistry.proceedResolution(InstanceRegistry.kt:87)
org.koin.core.instance.InstanceRegistry.resolve(InstanceRegistry.kt:61)
org.koin.android.ext.koin.ContextExtKt.androidContext(ContextExt.kt:42)
us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest$testModule$1$1.invoke(MovieDatabaseTest.kt:34)
us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest$testModule$1$1.invoke(MovieDatabaseTest.kt:26)
org.koin.core.instance.holder.InstanceHolder$DefaultImpls.create(InstanceHolder.kt:17)
org.koin.core.instance.holder.SingleInstanceHolder.create(SingleInstanceHolder.kt:10)
org.koin.core.instance.holder.SingleInstanceHolder.get(SingleInstanceHolder.kt:19)
org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:53)
org.koin.core.instance.InstanceRegistry$resolveInstance$1.invoke(InstanceRegistry.kt:138)
org.koin.core.instance.InstanceRegistry$resolveInstance$1.invoke(InstanceRegistry.kt:39)
org.koin.core.stack.ResolutionStack.resolve(ResolutionStack.kt:44)
org.koin.core.instance.InstanceRegistry.resolveInstance(InstanceRegistry.kt:137)
org.koin.core.instance.InstanceRegistry.access$resolveInstance(InstanceRegistry.kt:39)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$2.invoke(InstanceRegistry.kt:98)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$2.invoke(InstanceRegistry.kt:39)
org.koin.core.time.DurationKt.logDuration(Duration.kt:11)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:97)
org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:39)
org.koin.core.time.DurationKt.measureDuration(Duration.kt:19)
org.koin.core.instance.InstanceRegistry.proceedResolution(InstanceRegistry.kt:87)
org.koin.core.instance.InstanceRegistry.resolve(InstanceRegistry.kt:61)
us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest$$special$$inlined$inject$1.invoke(KoinComponent.kt:143)
kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest.getMovieDatabase(Unknown Source:7)
us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest.tearDown(MovieDatabaseTest.kt:45)
java.lang.reflect.Method.invoke(Native Method)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:80)
org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
org.junit.rules.RunRules.evaluate(RunRules.java:20)
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
org.junit.runners.ParentRunner.run(ParentRunner.java:363)
org.junit.runners.Suite.runChild(Suite.java:128)
org.junit.runners.Suite.runChild(Suite.java:27)
org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
org.junit.runners.ParentRunner.run(ParentRunner.java:363)
org.junit.runner.JUnitCore.run(JUnitCore.java:137)
org.junit.runner.JUnitCore.run(JUnitCore.java:115)
androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2075)
at org.koin.core.instance.holder.InstanceHolder$DefaultImpls.create(InstanceHolder.kt:23)
at org.koin.core.instance.holder.SingleInstanceHolder.create(SingleInstanceHolder.kt:10)
at org.koin.core.instance.holder.SingleInstanceHolder.get(SingleInstanceHolder.kt:19)
at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:53)
at org.koin.core.instance.InstanceRegistry$resolveInstance$1.invoke(InstanceRegistry.kt:138)
at org.koin.core.instance.InstanceRegistry$resolveInstance$1.invoke(InstanceRegistry.kt:39)
at org.koin.core.stack.ResolutionStack.resolve(ResolutionStack.kt:44)
at org.koin.core.instance.InstanceRegistry.resolveInstance(InstanceRegistry.kt:137)
at org.koin.core.instance.InstanceRegistry.access$resolveInstance(InstanceRegistry.kt:39)
at org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$2.invoke(InstanceRegistry.kt:98)
at org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1$2.invoke(InstanceRegistry.kt:39)
at org.koin.core.time.DurationKt.logDuration(Duration.kt:11)
at org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:97)
at org.koin.core.instance.InstanceRegistry$proceedResolution$$inlined$synchronized$lambda$1.invoke(InstanceRegistry.kt:39)
at org.koin.core.time.DurationKt.measureDuration(Duration.kt:19)
at org.koin.core.instance.InstanceRegistry.proceedResolution(InstanceRegistry.kt:87)
at org.koin.core.instance.InstanceRegistry.resolve(InstanceRegistry.kt:61)
at us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest$$special$$inlined$inject$1.invoke(KoinComponent.kt:143)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest.getMovieDatabase(Unknown Source:7)
at us.kostenko.architecturecomponentstmdb.details.repository.MovieDatabaseTest.tearDown(MovieDatabaseTest.kt:45)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:80)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2075)
这里也是我的
non-testing
我用它启动的模块定义
startKoin(this, listOf(baseModule, movieDetailModule))
从我的应用程序实现:
val baseModule = module {
factory<Coroutines> { AndroidCoroutines() }
single { Room.databaseBuilder(androidContext(), MovieDatabase::class.java, "movies-db")
.fallbackToDestructiveMigration().build() }
single { TmdbRetrofitBuilder(androidContext()).buildRetrofit() }
}
val movieDetailModule = module {
single { get<MovieDatabase>().detailDao() }
single<MovieWebService>{ get<Retrofit>().create(MovieWebService::class.java) }
single<MovieDetailRepository>{ MovieDetailRepositoryImpl(get(), get(), get()) }
viewModel { MovieDetailViewModel(get(), get()) }
}
看来这和
movieDatabase.close()
行,但我无法计算出在测试之间工作的配置。