如何测试注入了 Koin 的 viewModel?
How to test my viewModel that is Koin injected?
我有一个 ViewModel。它调用我的数据存储库中的一个函数并返回狗对象的列表。
class MainViewModel() : ViewModel() {
private val dataRepo: DataRepo by inject(DataRepo::class.java) //dataRepo
private var limit = 10
private val _dogListLiveData = MutableLiveData<List<Dog>>()
private var dogList = mutableListOf<Dog>()
val dogListLiveData: MutableLiveData<List<Dog>>
get() = _dogListLiveData
fun searchByBreed(queryText: String) {
dataRepo.searchByBreed(
queryText,
object : DataSource.OnResponseCallback<List<Dog>, String> {
override fun onSuccess(obj: List<Dog>?) {
dogList = mutableListOf()
if(!obj.isNullOrEmpty()){
dogList.addAll(obj)
dogListLiveData.value = dogList.take(limit)
}
}
override fun onError(error: String) {
Log.i("Calling Network Service", error)
}
})
}
fun loadPaginateBreed() : Boolean{
return if ((limit+10) < dogList.size) {
limit += 10
Log.i("Pagination new Limit", limit.toString())
dogListLiveData.value = dogList.take(limit)
false
}else{
limit += dogList.size%limit
dogListLiveData.value = dogList.take(limit)
true
}
}
}
我需要为它写一个简单的单元测试。我写了这个并尝试了许多其他迭代。但似乎没有任何效果。
package com.example.koinapplication.ui.main
import androidx.lifecycle.Observer
import com.example.koinapplication.custom.adpaters.GranularErrorCallAdapterFactory
import com.example.koinapplication.models.Dog
import com.example.koinapplication.models.Height
import com.example.koinapplication.models.Weight
import com.example.koinapplication.repo.*
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.Assert.*
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
import org.koin.java.KoinJavaComponent.inject
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import java.util.*
class MainViewModelTest {
private val mainViewModel: MainViewModel by inject(MainViewModel::class.java)
lateinit var obserserData : Observer<List<Dog>>
private val networkModule = module {
factory { AuthInterceptor() }
factory { provideOkHttpClient(get()) }
factory { GranularErrorCallAdapterFactory<Any>() }
single { providesNetworkClient(get(), get()) }
single { DataRepo(get()) }
single { NetworkRepo(get()) }
}
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
startKoin {
modules(arrayListOf(networkModule))
}
}
@After
fun tearDown() {
stopKoin()
}
@Test
fun searchByBreed() {
mainViewModel.dogListLiveData.observeForever { obserserData }
mainViewModel.searchByBreed("dal")
Mockito.verify(obserserData).onChanged(mainViewModel.dogListLiveData.value)
}
}
请帮我写一个简单的测试来测试我的 viewModel 中的数据。非常感谢您的帮助。
将所有依赖注入 (DI) 框架排除在 ViewModel 之外是一种很好的做法。这使您的 ViewModel 独立并简化了单元测试。
ViewModel
因此,您可以通过构造函数传递它们,而不是在 ViewModel 中注入依赖项:
class MainViewModel(
private val dataRepo: dataRepo
) : ViewModel() {
// ...
}
Koin 模块
在您的 Koin 模块中,您可以定义依赖项并提供您的 ViewModel 实例:
module {
single { DataRepo(get()) }
factory { MainViewModel(dataRepo = get())}
}
在您的 Activity 或 Fragment 中,您可以像往常一样注入您的 ViewModel。
单元测试
在您的 MainViewModelTest
中,您不需要任何 Koin 代码:
class MainViewModelTest {
private val dataRepo: DataRepo = mockk() // I used Mockk for mocking, but you can use any other mocking framework
private val mainViewModel = MainViewModel(dataRepo) // your class under test
@Test
fun yourTest() {
// prepare
every { dataRepo.searchByBreed(...)} returns ...
mainViewModel.searchByBreed(queryText = "...")
// do assertions
}
}
有了这个,大大简化了单元测试的编写。以后您可以将 Koin 与任何其他 DI 框架交换,而无需触及您的 ViewModel 和测试。
希望对您有所帮助。
我有一个 ViewModel。它调用我的数据存储库中的一个函数并返回狗对象的列表。
class MainViewModel() : ViewModel() {
private val dataRepo: DataRepo by inject(DataRepo::class.java) //dataRepo
private var limit = 10
private val _dogListLiveData = MutableLiveData<List<Dog>>()
private var dogList = mutableListOf<Dog>()
val dogListLiveData: MutableLiveData<List<Dog>>
get() = _dogListLiveData
fun searchByBreed(queryText: String) {
dataRepo.searchByBreed(
queryText,
object : DataSource.OnResponseCallback<List<Dog>, String> {
override fun onSuccess(obj: List<Dog>?) {
dogList = mutableListOf()
if(!obj.isNullOrEmpty()){
dogList.addAll(obj)
dogListLiveData.value = dogList.take(limit)
}
}
override fun onError(error: String) {
Log.i("Calling Network Service", error)
}
})
}
fun loadPaginateBreed() : Boolean{
return if ((limit+10) < dogList.size) {
limit += 10
Log.i("Pagination new Limit", limit.toString())
dogListLiveData.value = dogList.take(limit)
false
}else{
limit += dogList.size%limit
dogListLiveData.value = dogList.take(limit)
true
}
}
}
我需要为它写一个简单的单元测试。我写了这个并尝试了许多其他迭代。但似乎没有任何效果。
package com.example.koinapplication.ui.main
import androidx.lifecycle.Observer
import com.example.koinapplication.custom.adpaters.GranularErrorCallAdapterFactory
import com.example.koinapplication.models.Dog
import com.example.koinapplication.models.Height
import com.example.koinapplication.models.Weight
import com.example.koinapplication.repo.*
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.Assert.*
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
import org.koin.java.KoinJavaComponent.inject
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import java.util.*
class MainViewModelTest {
private val mainViewModel: MainViewModel by inject(MainViewModel::class.java)
lateinit var obserserData : Observer<List<Dog>>
private val networkModule = module {
factory { AuthInterceptor() }
factory { provideOkHttpClient(get()) }
factory { GranularErrorCallAdapterFactory<Any>() }
single { providesNetworkClient(get(), get()) }
single { DataRepo(get()) }
single { NetworkRepo(get()) }
}
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
startKoin {
modules(arrayListOf(networkModule))
}
}
@After
fun tearDown() {
stopKoin()
}
@Test
fun searchByBreed() {
mainViewModel.dogListLiveData.observeForever { obserserData }
mainViewModel.searchByBreed("dal")
Mockito.verify(obserserData).onChanged(mainViewModel.dogListLiveData.value)
}
}
请帮我写一个简单的测试来测试我的 viewModel 中的数据。非常感谢您的帮助。
将所有依赖注入 (DI) 框架排除在 ViewModel 之外是一种很好的做法。这使您的 ViewModel 独立并简化了单元测试。
ViewModel
因此,您可以通过构造函数传递它们,而不是在 ViewModel 中注入依赖项:
class MainViewModel(
private val dataRepo: dataRepo
) : ViewModel() {
// ...
}
Koin 模块
在您的 Koin 模块中,您可以定义依赖项并提供您的 ViewModel 实例:
module {
single { DataRepo(get()) }
factory { MainViewModel(dataRepo = get())}
}
在您的 Activity 或 Fragment 中,您可以像往常一样注入您的 ViewModel。
单元测试
在您的 MainViewModelTest
中,您不需要任何 Koin 代码:
class MainViewModelTest {
private val dataRepo: DataRepo = mockk() // I used Mockk for mocking, but you can use any other mocking framework
private val mainViewModel = MainViewModel(dataRepo) // your class under test
@Test
fun yourTest() {
// prepare
every { dataRepo.searchByBreed(...)} returns ...
mainViewModel.searchByBreed(queryText = "...")
// do assertions
}
}
有了这个,大大简化了单元测试的编写。以后您可以将 Koin 与任何其他 DI 框架交换,而无需触及您的 ViewModel 和测试。
希望对您有所帮助。