我如何测试响应期间出现的分页列表 return 错误?
How I can test what paged list return error during response?
我正在尝试测试 PagedList 数据源中的错误(加载新数据组时)。我的数据源看起来像这样:
package com.ps.superheroapp.ui.character_screen.list
import androidx.paging.PositionalDataSource
import com.ps.superheroapp.api.MarvelApiService
import com.ps.superheroapp.objects.SchedulerNames
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Named
class CharactersDataSource(
private val compositeDisposable: CompositeDisposable,
private val marvelApi: MarvelApiService,
@Named(SchedulerNames.MAIN) private val scheduler: Scheduler,
private val filter: Filter
) : PositionalDataSource<Character>() {
var events: SourcedDataEventsHandler? = null
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
compositeDisposable.add(marvelApi.searchCharacter(params.pageSize, 0, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
events?.onLoadStarted()
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf(), 0)
events?.onLoadFinishedSuccessfully()
}, {
events?.onLoadFinishedWithError(it)
})
)
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
compositeDisposable.add(
marvelApi.searchCharacter(params.loadSize, params.startPosition, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
events?.onLoadStarted()
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf())
events?.onLoadFinishedSuccessfully()
}, {
events?.onLoadFinishedWithError(it)
})
)
}
}
如果我只模拟事件处理程序 class 并在测试期间从中调用方法,则此测试不会测试任何内容。
我搜索了测试此类行为的方法或最佳实践,但没有找到任何东西。
我的测试是这样的:
@Test
fun should_show_network_error_when_screen_data_cannot_be_loaded_because_of_internet_connection() {
`when`(connectivityChecker.isOffline()).thenReturn(true)
//logic to imitate error during loading from data source
vm.fetchCharacters()
Assert.assertEquals(ErrorType.NETWORK, vm.error.get())
}
能否请您给我一些建议或架构示例,或单元测试示例来测试它。
提前致谢
我找到了下一个可行的解决方案:
我更改了数据源中 PublishSubject 的回调接口:
class CharactersDataSource(
private val compositeDisposable: CompositeDisposable,
private val marvelApi: MarvelApiService,
@Named(SchedulerNames.MAIN) private val scheduler: Scheduler,
val filter: Filter
) : PositionalDataSource<Character>() {
private val onEvent = PublishSubject.create<CharacterLoadEvent>()
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
compositeDisposable.add(marvelApi.searchCharacter(params.pageSize, 0, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
onEvent.onNext(CharacterLoadEvent.LOAD_STARTED)
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf(), 0)
onEvent.onNext(CharacterLoadEvent.LOADED)
}, {
onEvent.onNext(CharacterLoadEvent.ERROR)
})
)
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
compositeDisposable.add(
marvelApi.searchCharacter(params.loadSize, params.startPosition, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
onEvent.onNext(CharacterLoadEvent.LOAD_STARTED)
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf())
onEvent.onNext(CharacterLoadEvent.LOADED)
}, {
onEvent.onNext(CharacterLoadEvent.ERROR)
})
)
}
fun observeCharactersLoadEvents(): Observable<CharacterLoadEvent> = onEvent
}
并正在测试此发布者的模拟行为。
几个测试看起来像:
@Test
fun should_show_network_error_when_screen_data_cannot_be_loaded_because_of_internet_connection() {
`when`(connectivityChecker.isOffline()).thenReturn(true)
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.ERROR))
`when`(interactor.getCharacters()).then {
TestPageList.get<Character>(listOf())
}
vm.fetchCharacters()
Assert.assertEquals(ErrorType.NETWORK, vm.error.get())
}
@Test
fun should_show_general_error_when_screen_data_cannot_be_loaded_because_of_unknown_error() {
`when`(connectivityChecker.isOffline()).thenReturn(false)
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.ERROR))
vm.fetchCharacters()
Assert.assertEquals(ErrorType.GENERAL, vm.error.get())
}
@Test
fun should_filter_character_list_when_user_enter_text_in_search_field() {
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.LOAD_STARTED))
`when`(interactor.getCharacters()).then {
TestPageList.get<Character>(listOf())
}
vm.searchQuery.value = "Hulk"
Mockito.verify(interactor, times(1)).getCharacters("Hulk")
}
这有助于测试 DataSource 的行为,它对我有用。
我也将非常感谢任何改进此 Architecture/Approach/Test
的想法
我正在尝试测试 PagedList 数据源中的错误(加载新数据组时)。我的数据源看起来像这样:
package com.ps.superheroapp.ui.character_screen.list
import androidx.paging.PositionalDataSource
import com.ps.superheroapp.api.MarvelApiService
import com.ps.superheroapp.objects.SchedulerNames
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Named
class CharactersDataSource(
private val compositeDisposable: CompositeDisposable,
private val marvelApi: MarvelApiService,
@Named(SchedulerNames.MAIN) private val scheduler: Scheduler,
private val filter: Filter
) : PositionalDataSource<Character>() {
var events: SourcedDataEventsHandler? = null
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
compositeDisposable.add(marvelApi.searchCharacter(params.pageSize, 0, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
events?.onLoadStarted()
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf(), 0)
events?.onLoadFinishedSuccessfully()
}, {
events?.onLoadFinishedWithError(it)
})
)
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
compositeDisposable.add(
marvelApi.searchCharacter(params.loadSize, params.startPosition, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
events?.onLoadStarted()
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf())
events?.onLoadFinishedSuccessfully()
}, {
events?.onLoadFinishedWithError(it)
})
)
}
}
如果我只模拟事件处理程序 class 并在测试期间从中调用方法,则此测试不会测试任何内容。
我搜索了测试此类行为的方法或最佳实践,但没有找到任何东西。
我的测试是这样的:
@Test
fun should_show_network_error_when_screen_data_cannot_be_loaded_because_of_internet_connection() {
`when`(connectivityChecker.isOffline()).thenReturn(true)
//logic to imitate error during loading from data source
vm.fetchCharacters()
Assert.assertEquals(ErrorType.NETWORK, vm.error.get())
}
能否请您给我一些建议或架构示例,或单元测试示例来测试它。 提前致谢
我找到了下一个可行的解决方案:
我更改了数据源中 PublishSubject 的回调接口:
class CharactersDataSource(
private val compositeDisposable: CompositeDisposable,
private val marvelApi: MarvelApiService,
@Named(SchedulerNames.MAIN) private val scheduler: Scheduler,
val filter: Filter
) : PositionalDataSource<Character>() {
private val onEvent = PublishSubject.create<CharacterLoadEvent>()
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
compositeDisposable.add(marvelApi.searchCharacter(params.pageSize, 0, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
onEvent.onNext(CharacterLoadEvent.LOAD_STARTED)
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf(), 0)
onEvent.onNext(CharacterLoadEvent.LOADED)
}, {
onEvent.onNext(CharacterLoadEvent.ERROR)
})
)
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
compositeDisposable.add(
marvelApi.searchCharacter(params.loadSize, params.startPosition, filter.searchQuery)
.observeOn(scheduler)
.doOnSubscribe {
onEvent.onNext(CharacterLoadEvent.LOAD_STARTED)
}
.subscribe({
callback.onResult(it.data.results ?: arrayListOf())
onEvent.onNext(CharacterLoadEvent.LOADED)
}, {
onEvent.onNext(CharacterLoadEvent.ERROR)
})
)
}
fun observeCharactersLoadEvents(): Observable<CharacterLoadEvent> = onEvent
}
并正在测试此发布者的模拟行为。 几个测试看起来像:
@Test
fun should_show_network_error_when_screen_data_cannot_be_loaded_because_of_internet_connection() {
`when`(connectivityChecker.isOffline()).thenReturn(true)
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.ERROR))
`when`(interactor.getCharacters()).then {
TestPageList.get<Character>(listOf())
}
vm.fetchCharacters()
Assert.assertEquals(ErrorType.NETWORK, vm.error.get())
}
@Test
fun should_show_general_error_when_screen_data_cannot_be_loaded_because_of_unknown_error() {
`when`(connectivityChecker.isOffline()).thenReturn(false)
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.ERROR))
vm.fetchCharacters()
Assert.assertEquals(ErrorType.GENERAL, vm.error.get())
}
@Test
fun should_filter_character_list_when_user_enter_text_in_search_field() {
`when`(interactor.observeCharactersLoadEvents()).thenReturn(Observable.just(CharacterLoadEvent.LOAD_STARTED))
`when`(interactor.getCharacters()).then {
TestPageList.get<Character>(listOf())
}
vm.searchQuery.value = "Hulk"
Mockito.verify(interactor, times(1)).getCharacters("Hulk")
}
这有助于测试 DataSource 的行为,它对我有用。 我也将非常感谢任何改进此 Architecture/Approach/Test
的想法