我目前正在尝试为ViewModel类编写一个测试。我已经设法为其LiveData更新和已验证的行为编写了一些测试。
但是,当我尝试使用链接的方法测试方法,并查看链接的LiveData是否正确更新时,则没有任何反应。测试给出错误,指出在测试过程中未发生任何调用。
下面是我尝试测试LiveData对象的方式
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))
}
--->这是测试失败
@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))
}
这是我的ViewModel类,该类调用一些用例并从远程连接中获取数据:
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")
}
}
我想要实现的是,每当用户尝试获取有关带有条形码的产品的信息时,实际上并未存储在系统中,我们将得到一个空列表作为响应,在这种情况下,ViewModel应该发布通过warningMessage LiveData发出警告消息。
但是,在编写的测试中,我在调试mod中根本看不到“ handleQueryResult”函数已被调用。我正在为这个问题而苦苦挣扎,而且由于我对Mockito有点陌生,所以我无法理解我的测试出了什么问题。欢迎任何帮助。非常感谢。