I'm trying to write a test for my view model that gets the data from datastore but I can't figure it out. this is my data store implementation. I save the user data such as email and token when user is sign up or sign in :
class FlowAuthenticationDataStore(context: Context) : AuthenticationDataStore {
private val dataStore = context.createDataStore(name = "user_auth")
private val userEmailKey = preferencesKey<String>(name = "USER_EMAIL")
private val userTokenKey = preferencesKey<String>(name = "USER_TOKEN")
private val userNameKey = preferencesKey<String>(name = "USER_NAME")
private val userIsLoginKey = preferencesKey<Boolean>(name = "USER_IS_LOGIN")
override suspend fun updateUser(userDataStore: UserDataStoreModel) {
dataStore.edit {
it[userEmailKey] = userDataStore.email
it[userTokenKey] = userDataStore.token
it[userNameKey] = userDataStore.name
it[userIsLoginKey] = userDataStore.isLogin
}
}
override fun observeUser(): Flow<UserDataStoreModel> {
return dataStore.data.catch {
if (it is IOException) {
emit(emptyPreferences())
} else {
throw it
}
}.map {
UserDataStoreModel(
it[userIsLoginKey]!!,
it[userNameKey]!!,
it[userEmailKey]!!,
it[userTokenKey]!!
)
}
}
}
and this is my view model. I observe the user data store and if its success and has a data then I update my live data. If there is not data and user is first time to register then my live data is equal to default value from data class :
class SplashScreenViewModel(
private val flowOnBoardingDataStore: FlowAuthenticationDataStore,
private val contextProvider: CoroutineContextProvider,
) :
ViewModel() {
private val _submitState = MutableLiveData<UserDataStoreModel>()
val submitState: LiveData<UserDataStoreModel> = _submitState
fun checkUserLogin() {
viewModelScope.launch {
kotlin.runCatching {
withContext(contextProvider.io) {
flowOnBoardingDataStore.observeUser().collect {
_submitState.value = it
}
}
}.onFailure {
_submitState.value = UserDataStoreModel()
}
}
}
}
and this is my test class:
@ExperimentalCoroutinesApi
class SplashScreenViewModelTest {
private val dispatcher = TestCoroutineDispatcher()
@get:Rule
val rule = InstantTaskExecutorRule()
@get:Rule
val coroutineTestRule = CoroutineTestRule(dispatcher)
@RelaxedMockK
lateinit var flowOnBoardingDataStore: FlowAuthenticationDataStore
private fun createViewModel()=SplashScreenViewModel(flowOnBoardingDataStore,
CoroutineContextProvider(dispatcher,dispatcher)
)
@Before
fun setup() {
MockKAnnotations.init(this)
}
@After
fun tearDown() {
unmockkAll()
}
@Test
fun `when user is already sign in, then state should return model`()=dispatcher.runBlockingTest {
val viewModel=createViewModel()
val userDataStoreModel= UserDataStoreModel(true,"test","test","test")
flowOnBoardingDataStore.updateUser(userDataStoreModel)
viewModel.checkUserLogin()
assertEquals(userDataStoreModel,viewModel.submitState.value)
}
}
This is the result of my test function:
junit.framework.AssertionFailedError:
Expected :UserDataStoreModel(isLogin=true, name=test, email=test, token=test)
Actual :null
question from:
https://stackoverflow.com/questions/65856930/android-unit-testing-datastore 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…