如何测试具有由 android 生成的接口依赖项的 ViewModel 类作为单元测试

问题描述

大家好,我正在尝试测试我的 viewmodel 类并且它具有数据源的依赖性,我试图模拟它,但它不起作用,因为它是一个接口,我相信接口实现是在运行时生成的,如何我是否对这个类进行单元测试,下面是我的 viewmodel 类

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
       }
   }


这是我的 viewmodel 测试类

@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()
    }

我们将不胜感激。

解决方法

您可以按照 Mockito 的建议将您的依赖项包装在您拥有的类中 here。这也有一个好处,让您可以在不影响使用它的每个视图模型的情况下更改您的存储实现。