Skip to content

Instantly share code, notes, and snippets.

@arnyigor
Created May 5, 2022 06:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnyigor/5bfe1d499e40af4bd17239a49b148c6c to your computer and use it in GitHub Desktop.
Save arnyigor/5bfe1d499e40af4bd17239a49b148c6c to your computer and use it in GitHub Desktop.
Flow Unit testcase
//models
data class RequestData(val data:String)
class BusinessException(val msg:String):Throwable(msg)
//Interactor
interface IDataRequestInteractor {
suspend fun getData(): RequestData
}
// ViewModel
class MainViewModel @Inject constructor(
private val interactor: IDataRequestInteractor,
) : ViewModel() {
private val _loading = MutableStateFlow(true)
val loading = _loading.asStateFlow()
private val _data = MutableStateFlow("")
val data = _data.asStateFlow()
private val _error = MutableSharedFlow<String>(
extraBufferCapacity = 1,
onBufferOverflow = DROP_OLDEST
)
val error = _error.asSharedFlow()
private val _errorDialog = MutableSharedFlow<String>(
extraBufferCapacity = 1,
onBufferOverflow = DROP_OLDEST
)
val errorDialog = _errorDialog.asSharedFlow()
private val _connectionError = MutableSharedFlow<String>(
extraBufferCapacity = 1,
onBufferOverflow = DROP_OLDEST
)
val connectionError = _connectionError.asSharedFlow()
init {
loadData()
}
fun onRetryClick() {
loadData()
}
private fun loadData() {
viewModelScope.launch {
flow { emit(interactor.getData()) }
.onStart { startLoading() }
.onCompletion { finishLoading() }
.onEach { data ->
//тут куча всяких данных
_data.value = data.data
}
.catch { cause: Throwable -> setError(cause) }
.collect()
}
}
private fun startLoading() {
_loading.value = true
}
private fun finishLoading() {
_loading.value = false
}
private fun setError(throwable: Throwable) {
when (throwable) {
is BusinessException -> _errorDialog.tryEmit(throwable.message)
is HttpException ->_connectionError.tryEmit(throwable.message)
else ->_error.tryEmit(throwable.message)
}
}
}
//MainViewmodelUnitTest
class MainViewModelTest{
/*
init block
Для моков используем например мокито
*/
@Test
fun `load data has BusinessException EXPECT errorDialog`(): Unit = runBlockingTest {
interactor.stub {
onBlocking { getData() } doThrow BusinessException("Error")
}
val testResults = mutableListOf<String>()
val job = launch {
viewModel.errorDialog.toList(testResults)
}
viewModel.onRetryClick()// Проблема в том,что если убрать это, то testResults будет пустой
assertEquals(
"Error",
testResults.first()
)
job.cancel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment