Skip to content

Instantly share code, notes, and snippets.

View marcinOz's full-sized avatar
💙

Marcin marcinOz

💙
View GitHub Profile
@marcinOz
marcinOz / viewModel-testing.kt
Last active June 14, 2018 10:51
Kotlin ViewModel AAC
class MovieListViewModel @Inject constructor(private val dataProvider: DataProvider) : ViewModel() {
val movieDiscover = MutableLiveData<List<Movie>>()
fun fetchMovieDiscover() {
dataProvider.getMovieDiscover().subscribeBy(
onSuccess = { result -> movieDiscover.postValue(result)
},
onError = { error -> movieDiscover.postValue(null) }
)
sealed class ResourceState
class LoadingState : ResourceState()
class EmptyState : ResourceState()
data class PopulatedState<T>(val data: T) : ResourceState()
data class ErrorState(val message: String?) : ResourceState()
class MovieListViewModel @Inject constructor(private val dataProvider: DataProvider) : ViewModel() {
val movieDiscover = MutableLiveData<ResourceState>()
fun fetchMovieDiscover() {
movieDiscover.postValue(LoadingState())
dataProvider.getMovieDiscover().subscribeBy(
onSuccess = { result ->
if (result.isEmpty()) movieDiscover.postValue(EmptyState())
else movieDiscover.postValue(PopulatedState(result))
movieDiscover.observe(activity, Observer { it?.apply { updateView(this) }})
private fun updateView(resourceState: ResourceState) = when(resourceState) {
is LoadingState -> showLoading(true)
is PopulatedState<*> -> populate(resourceState.data as List<Movie>)
is EmptyState -> showEmptyMessage()
is ErrorState -> showError(resourceState.message)
}
sealed class ResourceState<T>
class LoadingState<T> : ResourceState<T>()
class EmptyState<T> : ResourceState<T>()
data class PopulatedState<T>(val data: T) : ResourceState<T>()
data class ErrorState<T>(val message: String?) : ResourceState<T>()
//MovieListViewModel
val movieDiscover = MutableLiveData<ResourceState<List<Movie>>>()
//View
private fun updateView(resourceState: ResourceState<List<Movie>>) = when(resourceState) {
is LoadingState -> showLoading(true)
is PopulatedState -> populate(resourceState.data)
is EmptyState -> showEmptyMessage()
is ErrorState -> showError(resourceState.message)
}
@Rule
@JvmField
val instantExecutorRule = InstantTaskExecutorRule() //Very very important
@Mock
private lateinit var dataProvider: DataProvider
@Mock lateinit var observer: Observer<ResourceState<List<Movie>>>
private lateinit var viewModel: MovieListViewModel
@Before
fun init() {
MockitoAnnotations.initMocks(this)
viewModel = MovieListViewModel(dataProvider)
.apply { movieDiscover.observeForever(observer) }
private fun mockFetchMovieDiscover(block: SingleEmitter<MovieDiscoveryResponse>.() -> Unit) {
`when`(dataProvider.getMovieDiscover()).thenReturn(Single.create { e -> e.block() })
}
@Test
fun fetchMovieDiscover_test_success_with_empty() {
mockFetchMovieDiscover { onSuccess(emptyList()) }
viewModel.fetchMovieDiscover()
sealed class ResourceState<T>
class LoadingState<T> : ResourceState<T>() {
override fun hashCode(): Int = javaClass.hashCode()
override fun equals(other: Any?) = equalz(other)
}
class EmptyState<T> : ResourceState<T>() {
override fun hashCode(): Int = javaClass.hashCode()
override fun equals(other: Any?) = equalz(other)
}