![](/img/trans.png)
[英]Koin Android: org.koin.error.NoBeanDefFoundException
[英]Android Test Koin NoBeanDefFoundException
我正在嘗試使用 Koin 進行一些 Android 測試,但到目前為止,還沒有成功。
我想用 Koin 注入的 ViewModel 測試基本活動。
我已經閱讀了類似NoBeanDefFoundException 和 Mock ViewModel 的帖子,用 Koin、Espresso 進行測試,但到目前為止我仍然有錯誤。
這是與測試配置相關的代碼
一個沒有模塊的特定應用程序。
class MyTestApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin { emptyList<Module>() }
}
}
使用測試應用程序的特定運行程序
class OccazioTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, MyTestApplication::class.java.name, context)
}
}
這是在我的應用程序build.gradle
定義的用作跑步者
android {
defaultConfig {
testInstrumentationRunner "fr.dsquad.occazio.occazio.OccazioTestRunner"
}
}
現在我想測試的代碼
在我的MyActivity
class MyActivity : AppCompatActivity(R.layout.activity_my) {
private val myViewModel by viewModel<MyViewModel>()
// Some code
}
和視圖模型
class MyViewModel(private val useCase: MyUseCase): ViewModel() {
// Some code
}
最后,測試本身(在 androidTest 中)
@LargeTest
class MyActivityTest : KoinTest {
private lateinit var mockUseCase: MyUseCase
@JvmField
@Rule
val activityRule = activityScenarioRule<MyActivity>()
@Before
fun setup() {
mockUseCase = mock(MyUseCase::class.java)
startKoin {
modules(module { viewModel { MyViewModel(mockUseCase) } })
}
// I've also tried this
loadKoinModules(
module { viewModel { MyViewModel(mockUseCase) } }
)
}
@After
fun cleanUp() {
stopKoin()
}
@Test
fun someTest() = runBlocking {
// Mock the usecase response
`when`(mockUseCase.doSomething()).thenReturn("taratata")
// Start the scenario
val scenario = activityRule.scenario
// Verify we call the getUserId
// Activity is supposed to call the view model that will call the method doSomethingAdterThat.
verify(mockUseCase, times(1)).doSomethingAfterThat()
return@runBlocking
}
}
到目前為止,每次運行此代碼時都會出現此錯誤
org.koin.core.error.NoBeanDefFoundException:
No definition found for 'mypackage.MyViewModel' has been found. Check your module definitions.
有趣的是,當
ActivityTestRule(SplashScreenActivity::class.java, true, false)
更改規則activityScenarioRule
val scenario = activityRule.scenario
更改為val scenario = activityRule.launchActivity(null)
setUp
使用loadKoinModules
而不是startKoin
發生兩件事
所以我在這里實際上有兩個問題。
activityScenarioRule
工作?好吧,不要問我它是如何工作的,但我想通了。
首先,因為我需要配置,所以我遵循了這個https://medium.com/stepstone-tech/better-tests-with-androidxs-activityscenario-in-kotlin-part-1-6a6376b713ea 。
我做了3件事
首先,我需要在啟動前配置 koin,為此,我需要使用ActivityScenario.launch()
和我之前定義的意圖
private val intent = Intent(ApplicationProvider.getApplicationContext(), MyActivity::class.java)
var activityRule : ActivityScenario<MyActivity>? = null
// And then I can start my activity calling
activityRule = ActivityScenario.launch(intent)
然后“KoinApp 沒有啟動”……我只是用 setUp 中的startKoin
替換了loadKoinModules
塊
startKoin { modules(module { viewModel { MyViewModel(mockUseCase) } }) }
最后,它適用於 1 個測試,但其他測試失敗,因為沒有調用像stopKoin()
這樣的“KoinAppAlreadyStartedException”。 所以我發現我應該擴展AutoCloseKoinTest
而不是KoinTest
.. 但沒有成功。 最后,我已經把stopKoin()
的前startKoin
而現在,一切工作就像一個魅力。
這是我的完整代碼
@LargeTest
class MyActivityTest : KoinTest() {
private val intent = Intent(ApplicationProvider.getApplicationContext(), MyActivity::class.java)
var activityRule : ActivityScenario<MyActivity>? = null
private lateinit var mockUseCase: MyUseCase
@Before
fun setup() {
mockUseCase = mock(MyUseCase::class.java)
stopKoin()
startKoin {
modules(module { viewModel { MyViewModel(mockUseCase) } })
}
}
@After
fun cleanUp() {
activityRule?.close()
}
@Test
fun someTest() = runBlocking {
// Mock the usecase response
`when`(mockUseCase.doSomething()).thenReturn("taratata")
// Start the rule
val activityRule = ActivityScenario.launch(intent)
// Verify we call the getUserId
// Activity is supposed to call the view model that will call the method doSomethingAdterThat.
verify(mockUseCase, times(1)).doSomethingAfterThat()
return@runBlocking
}
}
何,我也將此代碼添加到我的兩個Applications
override fun onTerminate() {
super.onTerminate()
stopKoin()
}
只是要確定 !
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.