Last active
July 25, 2019 20:34
-
-
Save fernandospr/c5bffbb7e179d27e4272211471d08325 to your computer and use it in GitHub Desktop.
LiveData+ViewModel+RxJava+LCE+Action+UnitTests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sealed class SampleAction { | |
object Action1 : SampleAction() | |
data class Action2WithParams(val param1: String, val param2: String) : SampleAction() | |
} | |
sealed class SampleResource { | |
object Loading : SampleResource() | |
object Error : SampleResource() | |
data class Success(val resource: MyResource) : SampleResource() | |
} | |
data class MyResource(val id: String) | |
class SampleViewModel : ViewModel() { | |
private val _resource = MutableLiveData<SampleResource>() | |
private val _action = SingleLiveEvent<SampleAction>() | |
private val composite = CompositeDisposable() | |
override fun onCleared() = composite.clear() | |
fun getResource(): LiveData<SampleResource> = _resource | |
fun getAction(): LiveData<SampleAction> = _action | |
fun fetchResource() { | |
_resource = SampleResource.Loading | |
composite.add( | |
someObservable | |
.subscribeOn(Schedulers.io()) | |
.observeOn(AndroidSchedulers.mainThread()) | |
.subscribeBy( | |
onSuccess = { _resource.value = SampleResource.Success(MyResource("Fernando")) } | |
onError = { _resource.value = SampleResource.Error } | |
) | |
) | |
} | |
fun operationResultingInAction() { | |
if (someLogic) { | |
_action.value = SampleAction.Action1 | |
} else { | |
_action.value = SampleAction.Action2WithParams("PARAM1", "PARAM2") | |
} | |
} | |
} | |
class SampleActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
... | |
viewModel.getResource().observe(this, Observer { | |
handleResource(it) | |
}) | |
viewModel.getAction().observe(this, Observer { | |
handleAction(it) | |
}) | |
} | |
private fun handleResource(it: SampleResource) { | |
when (it) { | |
is SampleResource.Loading -> showLoading() | |
is SampleResource.Error -> showError() | |
is SampleResource.SuccessWithParams -> showSuccess(it.resource) | |
} | |
} | |
private fun handleAction(it: SampleAction) { | |
when (it) { | |
is SampleAction.Action1 -> performAction1() | |
is SampleAction.Action2WithParams -> performAction2(it.param1, it.param2) | |
} | |
} | |
} | |
class SampleUnitTest { | |
@get:Rule | |
val rule = InstantTaskExecutorRule() | |
@get:Rule | |
val rxRule = RxSchedulerRule() | |
private lateinit var viewModel: SampleViewModel | |
private lateinit var actionObserver: Observer<SampleAction> | |
private lateinit var resourceObserver: Observer<SampleResource> | |
@Before | |
fun setup() { | |
actionObserver = mock() | |
resourceObserver = mock() | |
viewModel = SampleViewModel() | |
viewModel.getAction().observeForever(actionObserver) | |
viewModel.getResource().observeForever(resourceObserver) | |
} | |
@Test | |
fun fetchResource_shouldShowLoading() { | |
viewModel.fetchResource(...) | |
val expected = SampleResource.Loading | |
verify(resourceObserver).onChanged(eq(expected)) | |
} | |
@Test | |
fun fetchResource_shouldShowSuccess() { | |
viewModel.fetchResource(...) | |
val expected = SampleResource.SuccessWithParams(MyResource("Fernando")) | |
verify(resourceObserver).onChanged(eq(expected)) | |
} | |
@Test | |
fun fetchResource_shouldShowError() { | |
viewModel.fetchResource(...) | |
val expected = SampleResource.Error | |
verify(resourceObserver).onChanged(eq(expected)) | |
} | |
@Test | |
fun operation_shouldResultInAction1() { | |
viewModel.operationResultingInAction(...) | |
val expected = SampleAction.Action1 | |
verify(actionObserver).onChanged(eq(expected)) | |
} | |
@Test | |
fun operation_shouldResultInAction2() { | |
viewModel.operationResultingInAction(...) | |
val expected = SampleAction.Action2WithParams("Hello", "World") | |
verify(actionObserver).onChanged(eq(expected)) | |
} | |
} | |
class RxSchedulerRule : TestRule { | |
private val scheduler by lazy { Schedulers.trampoline() } | |
override fun apply(base: Statement?, description: Description?): Statement = | |
object : Statement() { | |
override fun evaluate() { | |
try { | |
RxJavaPlugins.setComputationSchedulerHandler { scheduler } | |
RxJavaPlugins.setIoSchedulerHandler { scheduler } | |
RxJavaPlugins.setNewThreadSchedulerHandler { scheduler } | |
RxJavaPlugins.setSingleSchedulerHandler { scheduler } | |
RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler } | |
base?.evaluate() | |
} finally { | |
RxJavaPlugins.reset() | |
RxAndroidPlugins.reset() | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment