【问题标题】:How to Unit Test MVVM with Koin?如何使用 Koin 对 MVVM 进行单元测试?
【发布时间】:2020-04-17 03:59:42
【问题描述】:

如何使用 Koin 对 MVVM 进行单元测试?

我正在尝试测试:link

但是,我不知道为什么我在 ViewModelTest 中得到error("No Data in ViewModel") fun getLookUpLeagueList()

存储库

class LookUpLeagueRepository {

    fun getLookUpLeague(idLeague: String): MutableLiveData<LookUpLeague> {
        val lookUpLeague = MutableLiveData<LookUpLeague>()
        APIService().getLookUpLeague(idLeague).enqueue(object : Callback<LookUpLeague> {
            override fun onFailure(call: Call<LookUpLeague>, t: Throwable) {
                d("TAG", "lookUpLeagueOnFailure ${t.localizedMessage}")
            }

            override fun onResponse(call: Call<LookUpLeague>, response: Response<LookUpLeague>) {
                lookUpLeague.value = response.body()
            }
        })
        return lookUpLeague
    }
}

视图模型

class LookUpLeagueViewModel(private val lookUpLeagueRepository: LookUpLeagueRepository) :
    ViewModel() {

    var lookUpLeagueList = MutableLiveData<LookUpLeague>()

    fun getLookUpLeagueList(idLeague: String) {
        lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
    }
}

模块

val lookUpLeagueModule = module {
    single { LookUpLeagueRepository() }
    viewModel { LookUpLeagueViewModel(get()) }
}

ViewModel 测试

class LookUpLeagueViewModelTest : KoinTest {

    val lookUpLeagueViewModel: LookUpLeagueViewModel by inject()

    val idLeague = "4328"

    @get:Rule
    val rule = InstantTaskExecutorRule()

    @Mock
    lateinit var observerData: Observer<LookUpLeague>

    @Before
    fun before() {
        MockitoAnnotations.initMocks(this)
        startKoin {
            modules(lookUpLeagueModule)
        }
    }

    @After
    fun after() {
        stopKoin()
    }

    @Test
    fun getLookUpLeagueList() {
        lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)

        lookUpLeagueViewModel.getLookUpLeagueList(idLeague)

        val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")

        Mockito.verify(observerData).onChanged(value)
    }
}

【问题讨论】:

    标签: android unit-testing kotlin mvvm koin


    【解决方案1】:
    @Test
    fun getLookUpLeagueList() {
        lookUpLeagueViewModel.lookUpLeagueList.observeForever(observerData)
        ...
    }
    

    此时lookUpLeagueListMutableLiveData 的一个实例。说这是MutableLiveData #1

    lookUpLeagueViewModel.getLookUpLeagueList(idLeague)
    

    执行上面的代码会调用LookUpLeagueViewModel.getLookUpLeagueList 函数。让我们来看看它的内部。

    lookUpLeagueList = lookUpLeagueRepository.getLookUpLeague(idLeague)
    

    LookUpLeagueRepository 内部创建了一个全新的MutableLiveData。这与observerData 正在观察的不同。此时lookUpLeagueViewModel.lookUpLeagueList指的是新的MutableLiveData #2,因为你重新分配给var lookUpLeagueList

    val value = lookUpLeagueViewModel.lookUpLeagueList.value ?: error("No Data in ViewModel")
    

    因此,您实际上是在查询MutableLiveData #2,它是新的、未观察到的并且是空的。这就是为什么valuenull。与其声明为var,不如声明为val。不要重新分配变量 setValuepostValue 来传播更改。

    【讨论】:

    猜你喜欢
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2019-11-02
    相关资源
    最近更新 更多