Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
479 views
in Technique[技术] by (71.8m points)

mvvm - How do I test a ViewModel class which has an interface dependecy that is generated by android as a Unit Test

Good day all, am trying to test my ViewModel class and it has a dependency of datasource, I tried to mock this, but it won't work because it's an interface, I believe the interface implementation is generated at runtime, how do I unit test this class, below is my ViewModel class

class LoginViewModel @ViewModelInject constructor(@ApplicationContext private val context: Context,
                                                 private val networkApi: NetworkAPI,
                                                 private val dataStore: DataStore<Preferences>)
   : ViewModel() {


   val clientNumber = MutableLiveData<String>()
   val clientPassword = MutableLiveData<String>()

   private val _shouldNavigate = MutableLiveData(false)
   val shouldNavigate: LiveData<Boolean>
       get() = _shouldNavigate

   private val _errorMessage = MutableLiveData<String>()
   val errorMessage: LiveData<String>
       get() = _errorMessage

private val _activateDeviceButton = MutableLiveData(false)
   val activateButton : LiveData<Boolean>
   get() = _activateDeviceButton

   init {
       populateApiWithFakeData()
   }


   suspend fun authenticateUsers(): Boolean {
       val clientNumber = clientNumber.value
       val clientPassword = clientPassword.value
       requireNotNull(clientNumber)
       requireNotNull(clientPassword)
       val (userExist, token) = networkApi.doesUserExist(clientNumber.toLong(), clientPassword)
       if (token.isNotBlank()) storeTokenInStore(token)
       return if (userExist) {
           true
       } else {
           _errorMessage.value = "Incorrect account details. Please try again with correct details"
           false
       }
   }

  private suspend fun storeTokenInStore(token: String) {
       dataStore.edit { pref ->
           pref[TOKEN_PREFERENCE] = token
       }
   }


and here is my ViewModel Test class

@Config(sdk = [Build.VERSION_CODES.O_MR1])
@RunWith(AndroidJUnit4::class)
class LoginViewModelTest{


    private val context : Context = ApplicationProvider.getApplicationContext()

    private val dataCentre = NetworkApImpl()

    @Mock
    private lateinit var dataStore: DataStore<Preferences>

    @Before
    fun setUpDataCenters(){
        val loginData = DataFactory.generateLoginData()
        for (data in loginData){
            dataCentre.saveUserData(data)
        }
    }

    @After
    fun tearDownDataCenter(){
        dataCentre.clearDataSet()
    }

    @Test
    @ExperimentalCoroutinesApi
    fun authenticateUser_shouldAuthenticateUsers(){
        //Given
        val viewModel = LoginViewModel(context, dataCentre, dataStore)
        viewModel.clientNumber.value = "8055675745"
        viewModel.clientPassword.value = "robin"
        //When
        var result : Boolean? = null
        runBlocking {
            result = viewModel.authenticateUsers()
        }
        //Then
        Truth.assertThat(result).isTrue()
    }

Any assistance rendered will be appreciated.

question from:https://stackoverflow.com/questions/65904527/how-do-i-test-a-viewmodel-class-which-has-an-interface-dependecy-that-is-generat

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can wrap your dependency in a class you own as Mockito suggests here. This also has the upside of letting you change your storage implementation latter without having and impact on every view model using it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...