基本上我还没有找到更好的方法来加载/卸载单 Activity 、多模块功能方法的模块。 fragment 附加和分离中模块的加载和卸载效果很好,直到涉及到 UI 测试为止。那么就不可能更换模块来测试模块。这确实工作得很好,但我希望能够以某种方式换入和换出模块以进行测试。
我在我的 fragment 中使用了这种方法
private val moduleList = arrayListOf(dataModule, viewmodelModule)
private val loadModules by lazy {
loadKoinModules(moduleList)
}
private fun injectFeatures() = loadModules
// Loading unloading modules
override fun onAttach(context: Context) {
super.onAttach(context)
injectFeatures()
}
override fun onDetach() {
unloadKoinModules(moduleList)
super.onDetach()
}
在我的测试中
@Before
fun setUp() {
loadKoinModules(listOf(testViewModelModule, testDataModule))
launchFragmentInContainer<MenuFragment>()
}
val dataModule = module {
single<IMenuRepository> { ImplMenuRepository(get()) }
single<NetworkDataSource> { FirebaseDataSource(get()) }
}
val testDataModule = module(override = true) {
single<IMenuRepository>(override = true) { FakeMenuRepository() }
}
这是我的错误
java.lang.RuntimeException: org.koin.core.error.DefinitionOverrideException: Definition '[Single:'com.nikolam.menu.data.IMenuRepository']' try to override existing definition. Please use override option or check for definition '[Single:'com.nikolam.menu.data.IMenuRepository']'
at androidx.test.runner.MonitoringInstrumentation.runOnMainSync(MonitoringInstrumentation.java:441)
at androidx.test.core.app.ActivityScenario.onActivity(ActivityScenario.java:564)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:300)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
at com.nikolam.menu.ui.menu.MenuItemsDisplayTest.setUp(MenuItemsDisplayTest.kt:66)
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.RunBefores.evaluate(RunBefores.java:76)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
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:2189)
Caused by: org.koin.core.error.DefinitionOverrideException: Definition '[Single:'com.nikolam.menu.data.IMenuRepository']' try to override existing definition. Please use override option or check for definition '[Single:'com.nikolam.menu.data.IMenuRepository']'
at org.koin.core.scope.ScopeDefinition.save(ScopeDefinition.kt:25)
at org.koin.core.scope.ScopeDefinition.save$default(ScopeDefinition.kt:19)
at org.koin.core.registry.ScopeRegistry.mergeDefinitions(ScopeRegistry.kt:95)
at org.koin.core.registry.ScopeRegistry.declareDefinitions(ScopeRegistry.kt:85)
at org.koin.core.registry.ScopeRegistry.declareScope(ScopeRegistry.kt:75)
at org.koin.core.registry.ScopeRegistry.loadModule(ScopeRegistry.kt:64)
at org.koin.core.registry.ScopeRegistry.loadModules$koin_core(ScopeRegistry.kt:55)
at org.koin.core.Koin.loadModules(Koin.kt:316)
at org.koin.core.context.ContextFunctionsKt.loadKoinModules(ContextFunctions.kt:60)
at com.nikolam.menu.ui.menu.MenuFragment$loadModules$2.invoke(MenuFragment.kt:28)
at com.nikolam.menu.ui.menu.MenuFragment$loadModules$2.invoke(MenuFragment.kt:22)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.nikolam.menu.ui.menu.MenuFragment.getLoadModules(Unknown Source:2)
at com.nikolam.menu.ui.menu.MenuFragment.injectFeatures(MenuFragment.kt:31)
at com.nikolam.menu.ui.menu.MenuFragment.onAttach(MenuFragment.kt:79)
at androidx.fragment.app.Fragment.performAttach(Fragment.java:2673)
at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:263)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1182)
at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1255)
at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1138)
at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:136)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2001)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1959)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1830)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:317)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:301)
at androidx.test.core.app.ActivityScenario.lambda$onActivity$2$ActivityScenario(ActivityScenario.java:551)
at androidx.test.core.app.ActivityScenario$$Lambda$4.run(Unknown Source:4)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:2207)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
如果有人在 Koin 和多功能模块项目上取得了成功,请填写我的信息。任何输入都会非常有帮助!
最佳答案
我知道这是一个相当老的问题,但也许答案可以帮助某人:您必须在声明中添加 override = true ,如下所示:
val dataModule = module {
single<IMenuRepository>(override = true) { ImplMenuRepository(get()) }
single<NetworkDataSource>(override = true) { FirebaseDataSource(get()) }
}
从 3.1.0 开始,不再需要此选项,因为他们更改了覆盖策略,现在默认为 true。
关于android - 在多功能模块应用程序中,我在哪里加载和卸载 Koin 模块并保持其可测试性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63540155/