代码之家  ›  专栏  ›  技术社区  ›  AlexKost

BeanInstanceCreationException:无法为单个

  •  3
  • AlexKost  · 技术社区  · 5 年前

    我试图在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() 行,但我无法计算出在测试之间工作的配置。

    1 回复  |  直到 5 年前
        1
  •  0
  •   Sreejith B Naick    5 年前

    我也有类似的问题。我想这跟 androidContext() androidApplication 模块定义中的用法。

    我通过以下方法解决了这个问题:

     @Before()
     fun before() {
         val context = ApplicationProvider.getApplicationContext<Application>()
         StandAloneContext.loadKoinModules(baseAppModule).with(context)
     }
    

    同样的事情是由 startKoin koin android扩展库文件中的方法 ComponentCallbacksExt.Kt

    试试看!!!!

        2
  •  0
  •   Priya    5 年前

    我也有类似的问题, 尝试只添加依赖项##

    // Room implementation "android.arch.persistence.room:runtime:1.1.1" kapt "android.arch.persistence.room:compiler:1.1.1"