我在SearchViewModel中有一个方法,我想通过Mockito和JUnit4测试此方法。(searchCity()) 但是运行测试后会显示此错误:
kotlin.UninitializedPropertyAccessException: lateinit属性mRepository尚未初始化
SearchViewModel类:
class SearchViewModel @Inject constructor() : BaseViewModel() {
@Inject
lateinit var mRepository: DataRepository
@Inject
lateinit var sharedPfs: SharedPrefs
private var disposable: Disposable? = null
val search = MutableLiveData<ResponseSearch>()
val searchOWM = MutableLiveData<ResponseOWMCity>()
val searchCityName = MutableLiveData<String>()
val serachClick = SingleLiveEvent<Boolean>()
val progressBar = SingleLiveEvent<Boolean>()
val searchOWMvisibility = SingleLiveEvent<Boolean>()
val cityOWMclick = SingleLiveEvent<ResponseOWMCity>()
override fun getSharedPrefs(): SharedPrefs? {
return sharedPfs
}
fun stop() {
disposable?.let { if (!it.isDisposed) it.dispose() }
}
fun fabSearchClick(){
serachClick.call()
}
fun searchCity() {
val cityName = searchCityName.value
if (!Strings.isEmptyOrWhitespace(cityName)) {
progressBar.postValue(true)
disposable = mRepository.doSearchProcess(cityName)
?.subscribe({
search.postValue(it)
progressBar.postValue(false)
}, {
showToast(it!!.message!!)
progressBar.postValue(false)
})
} else{
showToast("لطفا شهر دلخواه خود را وارد کنید.")
}
}
fun searchCityOWM() {
val cityName = searchCityName.value
disposable = mRepository.doSearchProcessOWM(cityName)
?.subscribe({
if (it != null){
searchOWM.postValue(it)
searchOWMvisibility.postValue(true)
} else{
searchOWMvisibility.postValue(false)
}
}, {
searchOWMvisibility.postValue(false)
})
}
fun clickCityOWM(city: ResponseOWMCity){
cityOWMclick.postValue(city)
}
}
DataRepository类:
class DataRepository @Inject
constructor(private val endPointAPI: EndPointAPI, private val localRoomDatabse: LocalRoomDatabse) {
fun getAllSavedResults(): LiveData<List<City?>>? {
return localRoomDatabse.roomDao().getAllResults()
}
fun doSearchProcess(city: String?): Observable<ResponseSearch>? {
return endPointAPI.searchCities(Config.BASE_URL2 + city)
.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.doOnError({ throwable -> Log.i("1397", "remote: " + throwable.message) })
}
}
SearchViewModelTest:
class SearchViewModelTest {
@get:Rule
val mockitoRule: MockitoRule = MockitoJUnit.rule()
@get:Rule
val taskExecutorRule = InstantTaskExecutorRule()
@Rule
@JvmField
var testSchedulerRule = RxImmediateSchedulerRule()
@Mock
lateinit var observer: Observer<ResponseSearch>
@Mock
lateinit var mRepository: DataRepository
lateinit var searchViewModel: SearchViewModel
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
searchViewModel = SearchViewModel()
}
@Test
fun doSearchResultSuccessWithData() {
// GIVEN
val res = RESULT()
res.name = "shiraz"
val list = ArrayList<RESULT>()
list.add(res)
val search = ResponseSearch(list)
val observable = Observable.just(search)
// WHEN
searchViewModel.searchCityName.value = "shiraz"
searchViewModel.search.observeForever(observer)
whenever(mRepository?.doSearchProcess("shiraz")).thenReturn(observable)
searchViewModel.searchCity()
// THEN
assertNotNull(searchViewModel.search.value)
assertThat(searchViewModel.search.value?.results?.size, CoreMatchers.`is`(1))
}
}
有人可以帮助我吗?
答案 0 :(得分:1)
在使用Dagger和字段注入时,在涉及ViewModels时,实际上应该使用组件或工厂注入它们。在测试期间,您可以注入在此处创建的模拟程序
@Mock
lateinit var mRepository: DataRepository
使用Dagger自动生成的代码
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
searchViewModel = SearchViewModel()
SearchViewModel_MembersInjector.injectMRepository(searchViewModel, mRepository)
}