I am currently trying to write a test for my ViewModel class. I already managed to write some tests for its LiveData updates, and verified behaviors.
However when I tried to test a method with chained methods, and see if my linked LiveData updated correctly, there is nothing happening. Test gives error stating that there is no invoke happened during test.
Below is how I tried to test the LiveData object
class WorkViewModelTest : AndroidTest() {
@Mock
private lateinit var sqlQueryUseCase: SqlQueryUseCase
private lateinit var workViewModel: WorkViewModel
val prefs = PreferencesHelper.defaultPrefs(context())
val resourceProvider = ResourceProvider(context())
@Before
fun setup() {
workViewModel = WorkViewModel(sqlQueryUseCase, prefs, resourceProvider)
workViewModel.toggleProductListState.observeForever {}
}
@Test
fun `When invalid barcode text given to function, it returns error message`() {
//given
val invalidString: String? = null
val observer = mock<Observer<String>>()
workViewModel.warningMessage.observeForever(observer)
//when
workViewModel.checkProductCode(invalidString)
//then
verify(observer).onChanged(resourceProvider.getStringFromResources(R.string.work_screen_empty_product_code_warning))
}
---> This is the test that fails
@Test
fun `When user read a barcode and it is not found on remote with ERP System, we should move our state to error`() {
//given
val barcode = "123456789"
val observer = mock<Observer<String>>()
workViewModel.warningMessage.observeForever(observer)
given {
runBlocking { sqlQueryUseCase.run(any()) }
}.willReturn(Either.Right(emptyList())
//when
runBlocking { workViewModel.checkProductCode(barcode) }
//then
verify(observer).onChanged(resourceProvider.getStringFromResources(R.string.work_screen_data_not_found_for_given_barcode_warning))
}
Here is my ViewModel class, which invokes some use cases and fetch data from remote connection:
class WorkViewModel
@Inject constructor(
private val sqlQueryUseCase: SqlQueryUseCase,
private val prefs: SharedPreferences,
private val resourceProvider: ResourceProvider
) : BaseViewModel() {
val productListState: MutableLiveData<Boolean> = MutableLiveData()
val itemList: MutableLiveData<List<ItemDetailModel>> = MutableLiveData()
val warningMessage: MutableLiveData<String> = MutableLiveData()
val productInformation: MutableLiveData<String> = MutableLiveData()
val toggleProductListState = Transformations.map(itemList) {
if (it.isEmpty()) {
productListState.postValue(false)
} else {
productListState.postValue(true)
}
}
fun initializeItemList(itemList: List<ItemDetailModel>) {
this.itemList.postValue(itemList)
}
fun checkProductCode(productCode: String?) {
if (productCode.isNullOrEmpty()) {
warningMessage.postValue(resourceProvider.getStringFromResources(R.string.work_screen_empty_product_code_warning))
} else {
executeSqlQuery(productCode)
}
}
private fun executeSqlQuery(productCode: String) {
sqlQueryUseCase(
SqlQueryUseCase.Params(
String.createAuthToken(PreferencesHelper.getAuthorizationToken(prefs)),
RequestBody.create(
MediaType.parse("application/json"),
QueryCreatorFactory.createQueryCreatorFromErpType(
prefs,
resourceProvider
).getProductInformationFromBarcodeQuery(productCode)!!.toByteArray(Charsets.UTF_8)
)
)
) {
it.either(::handleErrorState, ::handleQueryResult)
}
}
private fun handleQueryResult(resultData: List<Any>) {
if (resultData.isNotEmpty()) {
productInformation.postValue(resultData[0] as String)
} else {
warningMessage.postValue(resourceProvider.getStringFromResources(R.string.work_screen_data_not_found_for_given_barcode_warning))
}
}
private fun handleErrorState(failure: Failure) {
if (failure is Failure.ServerError)
warningMessage.postValue(failure.errorMessage)
else
warningMessage.postValue("Some other failure")
}
}
What I am trying to achieve is, whenever user tries to get information about a product with a barcode, which actually does not stored in system, we will get an empty list as a response, and at that case, ViewModel should post a warning message via warningMessage LiveData.
However with the test I wrote, I cannot see in debug mod that "handleQueryResult" function is called at all. I am struggling with that problem, and since I am a bit new with Mockito, I cannot understand what is wrong with my test. Any help is welcomed. Thanks a lot.
Aucun commentaire:
Enregistrer un commentaire