kotlin.UninitializedPropertyAccessException:lateinit属性mRepository尚未初始化

时间:2019-08-12 13:30:01

标签: android mvvm mockito viewmodel junit4

我在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))

    }
}

有人可以帮助我吗?

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)
}