【发布时间】:2020-09-11 14:47:38
【问题描述】:
我正在尝试使用 Koin 进行一些 Android 测试,但到目前为止,还没有成功。
我想用 Koin 注入的 ViewModel 测试一个基本的 Activity。
我已经阅读了NoBeanDefFoundException with Mock ViewModel, testing with 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.
有趣的是,当
- 我将规则
activityScenarioRule更改为旧的已弃用ActivityTestRule(SplashScreenActivity::class.java, true, false) - 我将
val scenario = activityRule.scenario更改为val scenario = activityRule.launchActivity(null) - 我在
setUp中使用loadKoinModules而不是startKoin
发生了两件事
- 当我的测试单独开始时(通过 Android Studio):它通过了。
- 当我的测试与其他测试一起开始时(通过类或使用 connectedAndroidTest),只有其中一个通过,而其他的都是 KO。
所以我实际上有两个问题。
- 如何使用
activityScenarioRule进行此测试? - 我怎样才能让它们“全部”工作(而不是一个一个地启动它们以使它们工作)?
【问题讨论】:
-
你可以试试可以回答stackoverflow.com/a/51786897/1374991
标签: android kotlin testing android-espresso koin