我正试图开始测试同时使用RxJava,Retrofit和LiveData的视图模型,但始终具有:NullPointerException。 因此,这是我的SplashViewModel,它可以同时从三个url下载数据,如果一切正常,该函数应将数据保存在Room Database中。在我的测试中,我只想检查一个网址,因此val error = MutableLiveData()获得真实值。 我做错了什么?我该怎么办?如何正确测试这种情况?
lass SplashViewModel @Inject constructor(private val photoRepository: PhotoRepository,
private val albumRepository: AlbumRepository,
private val userRepository: UserRepository,
@CoroutineScopeIO private val ioCoroutineScope: CoroutineScope) : ViewModel() {
val loading = MutableLiveData<Boolean>()
val error = MutableLiveData<Boolean>()
private lateinit var disposable: Disposable
private val requests = ArrayList<Observable<*>>()
var photos = ArrayList<RawPhoto>()
var albums = ArrayList<RawAlbum>()
var users = ArrayList<RawUser>()
init {
fetchData()
}
fun fetchData() {
loading.postValue(true)
requests.add(photoRepository.getPhotos()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()))
requests.add(albumRepository.getAlbums()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()))
requests.add(userRepository.getUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()))
disposable = Observable.zip(requests){
if (it[0] is List<*>) { //photos
photos = it[0] as ArrayList<RawPhoto>
}
if (it[1] is List<*>) { //albums
albums = it[1] as ArrayList<RawAlbum>
}
if (it[2] is List<*>) { //users
users = it[2] as ArrayList<RawUser>
}
}
.subscribe({
ioCoroutineScope.launch {
photoRepository.insertPhotos(photos)
Timber.e("PHOTOS $photos")
}
ioCoroutineScope.launch {
albumRepository.insertAlbums(albums)
Timber.e("ALBUMS $albums")
}
ioCoroutineScope.launch {
userRepository.insertUsers(users)
Timber.e("USERS $users")
}
loading.postValue(false)
Timber.e("Success")
}) {
error.postValue(true)
Timber.e("Error")
}
}
override fun onCleared() {
super.onCleared()
disposable.dispose()
ioCoroutineScope.cancel()
}
}
测试类:
@RunWith(MockitoJUnitRunner::class)
class SplashViewModelTest {
@Mock
lateinit var photoRepository: PhotoRepository
@Mock
lateinit var albumRepository: AlbumRepository
@Mock
lateinit var userRepository: UserRepository
lateinit var splashViewModel: SplashViewModel
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
lateinit var mockWebServer: MockWebServer
private lateinit var observablePhotos: Observable<List<RawPhoto>>
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
mockWebServer = MockWebServer()
mockWebServer.start()
splashViewModel = SplashViewModel(photoRepository, albumRepository, userRepository, testScope)
}
@After
fun tearDown() {
mockWebServer.shutdown()
}
@Test
fun fetchJustOneUrl() {
val rawPhoto1 = RawPhoto(1, 1, "Title1", "url1", "thumbUrl1")
val rawPhoto2 = RawPhoto(2, 2, "Title2", "url2", "thumbUrl2")
var rawPhotoList = ArrayList<RawPhoto>()
rawPhotoList.add(rawPhoto1)
rawPhotoList.add(rawPhoto2)
observablePhotos = Observable.just(rawPhotoList)
if (photoRepository != null) {
Mockito.`when`(photoRepository.getPhotos()).thenReturn(observablePhotos)
}
splashViewModel.fetchData()
Assert.assertEquals(2, splashViewModel.error.value == true)
}
}