跳至主要内容

Android 檢測儀器化測試 (Android Instrumented Testing)

在自定義的 Application 類別中覆寫生產模組

單元測試 不同,在單元測試中,您可以在每個測試類別中有效地呼叫 start Koin (即 startKoinKoinTestExtension),在 Instrumented 測試中,Koin 由您的 Application 類別啟動。

為了覆寫生產 Koin 模組,loadModulesunloadModules 通常是不安全的,因為變更不會立即生效。 相反,建議的方法是將覆寫的 module 添加到 Application 類別中 startKoin 使用的 modules 中。 如果您想保持擴展應用程式的 Application 的類別不變,您可以在 AndroidTest 套件中建立另一個類別,例如:

class TestApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
modules(productionModule, instrumentedTestModule)
}
}
}

為了在您的 Instrumentation 測試中使用此自定義 Application,您可能需要建立一個自定義的 AndroidJUnitRunner,例如:

class InstrumentationTestRunner : AndroidJUnitRunner() {
override fun newApplication(
classLoader: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(classLoader, TestApplication::class.java.name, context)
}
}

然後在您的 gradle 檔案中註冊它:

testInstrumentationRunner "com.example.myapplication.InstrumentationTestRunner"

使用測試規則覆寫生產模組

如果您想要更大的靈活性,您仍然需要建立自定義的 AndroidJUnitRunner,但不是在自定義的 application 中使用 startKoin { ... },您可以將其放入自定義的測試規則中,例如:

class KoinTestRule(
private val modules: List<Module>
) : TestWatcher() {
override fun starting(description: Description) {

if (getKoinApplicationOrNull() == null) {
startKoin {
androidContext(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext)
modules(modules)
}
} else {
loadKoinModules(modules)
}
}

override fun finished(description: Description) {
unloadKoinModules(modules)
}
}

透過這種方式,我們可以潛在地直接從我們的測試類別中覆寫定義,例如:

private val instrumentedTestModule = module {
factory<Something> { FakeSomething() }
}

@get:Rule
val koinTestRule = KoinTestRule(
modules = listOf(productionModule, instrumentedTestModule)
)