如何使用 Koin 对 MVVM 进行单元测试?
How to Unit Test MVVM with Koin?
如何使用 Koin 对 MVVM 进行单元测试?
我已经尝试测试了:link
但是,我不知道为什么我在 ViewModelTest fun getLookUpLeagueList()
中得到 error("No Data in ViewModel")
存储库
class LookUpLeagueRepository {
fun getLookUpLeague(idLeague: String): MutableLiveData<LookUpLeague> {
val lookUpLeague = MutableLiveData<LookUpLeague>()
APIService().getLookUpLeague(idLeague).enqueue(object : Callback<LookUpLeague> {
override fun onFailure(call: Call<LookUpLeague>, t: Throwable) {
d("TAG", "lookUpLeagueOnFailure ${t.localizedMessage}")
}
override fun onResponse(call: Call<LookUpLeague>, response: Response<LookUpLeague>) {
lookUpLeague.value = response.body()
}
})
return lookUpLeague
}
}
视图模型
class LookUpLeagueViewModel(private val lookUpLeagueRepository: LookUpLeagueRepository) :
ViewModel() {
var lookUpLeagueList = MutableLiveData<LookUpLeague>()
fun getLookUpLeagueList(idLeague: String) {
lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
}
}
模块
val lookUpLeagueModule = module {
single { LookUpLeagueRepository() }
viewModel { LookUpLeagueViewModel(get()) }
}
ViewModel 测试
class LookUpLeagueViewModelTest : KoinTest {
val lookUpLeagueViewModel: LookUpLeagueViewModel by inject()
val idLeague = "4328"
@get:Rule
val rule = InstantTaskExecutorRule()
@Mock
lateinit var observerData: Observer<LookUpLeague>
@Before
fun before() {
MockitoAnnotations.initMocks(this)
startKoin {
modules(lookUpLeagueModule)
}
}
@After
fun after() {
stopKoin()
}
@Test
fun getLookUpLeagueList() {
lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)
lookUpLeagueViewModel.getLookUpLeagueList(idLeague)
val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")
Mockito.verify(observerData).onChanged(value)
}
}
@Test
fun getLookUpLeagueList() {
lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)
...
}
此时lookUpLeagueList
是MutableLiveData
的实例。假设这是 MutableLiveData #1
.
lookUpLeagueViewModel.getLookUpLeagueList(idLeague)
执行上面的行会调用LookUpLeagueViewModel.getLookUpLeagueList
函数。一起来看看吧。
lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
在 LookUpLeagueRepository
中创建了一个全新的 MutableLiveData
。这与 observerData
正在观察的那个不同。此时lookUpLeagueViewModel.lookUpLeagueList
指的是新的,MutableLiveData #2
因为你重新赋值给了var lookUpLeagueList
.
val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")
因此,您实际上是在查询 MutableLiveData #2
,它是新的、未观察到的并且是空的。这就是 value
是 null
的原因。与其声明为 var
,不如声明为 val
。不要重新分配变量,setValue
或 postValue
以传播更改。
如何使用 Koin 对 MVVM 进行单元测试?
我已经尝试测试了:link
但是,我不知道为什么我在 ViewModelTest fun getLookUpLeagueList()
error("No Data in ViewModel")
存储库
class LookUpLeagueRepository {
fun getLookUpLeague(idLeague: String): MutableLiveData<LookUpLeague> {
val lookUpLeague = MutableLiveData<LookUpLeague>()
APIService().getLookUpLeague(idLeague).enqueue(object : Callback<LookUpLeague> {
override fun onFailure(call: Call<LookUpLeague>, t: Throwable) {
d("TAG", "lookUpLeagueOnFailure ${t.localizedMessage}")
}
override fun onResponse(call: Call<LookUpLeague>, response: Response<LookUpLeague>) {
lookUpLeague.value = response.body()
}
})
return lookUpLeague
}
}
视图模型
class LookUpLeagueViewModel(private val lookUpLeagueRepository: LookUpLeagueRepository) :
ViewModel() {
var lookUpLeagueList = MutableLiveData<LookUpLeague>()
fun getLookUpLeagueList(idLeague: String) {
lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
}
}
模块
val lookUpLeagueModule = module {
single { LookUpLeagueRepository() }
viewModel { LookUpLeagueViewModel(get()) }
}
ViewModel 测试
class LookUpLeagueViewModelTest : KoinTest {
val lookUpLeagueViewModel: LookUpLeagueViewModel by inject()
val idLeague = "4328"
@get:Rule
val rule = InstantTaskExecutorRule()
@Mock
lateinit var observerData: Observer<LookUpLeague>
@Before
fun before() {
MockitoAnnotations.initMocks(this)
startKoin {
modules(lookUpLeagueModule)
}
}
@After
fun after() {
stopKoin()
}
@Test
fun getLookUpLeagueList() {
lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)
lookUpLeagueViewModel.getLookUpLeagueList(idLeague)
val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")
Mockito.verify(observerData).onChanged(value)
}
}
@Test
fun getLookUpLeagueList() {
lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)
...
}
此时lookUpLeagueList
是MutableLiveData
的实例。假设这是 MutableLiveData #1
.
lookUpLeagueViewModel.getLookUpLeagueList(idLeague)
执行上面的行会调用LookUpLeagueViewModel.getLookUpLeagueList
函数。一起来看看吧。
lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
在 LookUpLeagueRepository
中创建了一个全新的 MutableLiveData
。这与 observerData
正在观察的那个不同。此时lookUpLeagueViewModel.lookUpLeagueList
指的是新的,MutableLiveData #2
因为你重新赋值给了var lookUpLeagueList
.
val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")
因此,您实际上是在查询 MutableLiveData #2
,它是新的、未观察到的并且是空的。这就是 value
是 null
的原因。与其声明为 var
,不如声明为 val
。不要重新分配变量,setValue
或 postValue
以传播更改。