Android单元测试:如何模拟包含MutableLiveData但仅公开LiveData的对象?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android单元测试:如何模拟包含MutableLiveData但仅公开LiveData的对象?相关的知识,希望对你有一定的参考价值。

我有一个存储库类,该类使用MutableLiveData对象(仅作为LiveData公开)将异步Web查询的结果返回给ViewModel。然后,ViewModel使用Transformation将结果映射到另一个View观察到的MutableLiveData。

我认为我通过分离关注点遵循了本模块中推荐的体系结构,但是我发现很难为ViewModel编写单元测试:

class DataRepository ( private val webservice: DataWebService ) 

    private val _exception = MutableLiveData<Exception?>(null)
    val exception : LiveData<Exception?> get() = _exception

    private val _data = MutableLiveData<List<DataItem>>()

    val data: LiveData<List<DataItem>> = _data

    private val responseListener = Response.Listener<String> response ->
        try 
            val list = JsonReader(SearchResult.mapping).readObject(response).map 
                    //Data transformation
            
            _exception.value = null
            _data.value = list
         catch (ex: Exception) 
            _exception.value = ex
            _data.value = emptyList()
         
    

    fun findData(searchString: String) 
        _data.value = emptyList()
        webservice.findData(searchString, responseListener = responseListener)
     

class WebServiceDataViewModel (private val repository: DataRepository, app: App) : androidViewModel(app)


    val dataList: LiveData<List<DataItem>> = Transformations.map(repository.data) 
        _showEmpty.value = it.isEmpty()
        it
    
    val exception: LiveData<Exception?> get() = repository.exception

    private val _showEmpty = MutableLiveData(true)
    val showEmpty : LiveData<Boolean> = _showEmpty

    private var _reloadOnCreate = true

    var searchString: String? = null
        set(value) 
            field = value
            if (!value.isNullOrBlank()) 
                repository.findData(value)
            
        

ViewModel测试类:

@RunWith(JUnit4::class)
class WebServicePodcastViewModelTest 
    @Rule var instantExecutorRule = InstantTaskExecutorRule()

    @Mock lateinit var repository : DataRepository
    @Mock lateinit var app : App

    lateinit var viewModel: WebServiceDataViewModel

    @Mock lateinit var exceptionObserver : Observer<Exception?>
    @Mock lateinit var dataObserver : Observer<List<DataItem>>
    @Mock lateinit var showEmptyObserver : Observer<Boolean>

    @Before
    fun setUp() 
        MockitoAnnotations.initMocks(this)

        viewModel = WebServiceDataViewModel(repository, app)
        viewModel.exception.observeForever(exceptionObserver)
        viewModel.showEmpty.observeForever(showEmptyObserver)
        viewModel.dataList.observeForever(dataObserver)
    

    @Test
    fun searchForData() 
        //given
        val searchString = "MockSearch"
        //when
        `when`(repository.findData(searchString)).then  /* How to invoke the mock repositories LiveData? */ 
        //then
        //TODO: verify that ViewModel LiveData behaves as expected
    

因此,如何调用模拟类的不可变LiveData?目前,我正在尝试使用Mockito和JUnit,但是如果设置简单,我会接受不同的框架!

答案

最后,我抛弃了Mockito,改用MockK,它就像一个吊饰!

以上是关于Android单元测试:如何模拟包含MutableLiveData但仅公开LiveData的对象?的主要内容,如果未能解决你的问题,请参考以下文章

Android单元测试之Mockito的使用

Android单元测试与模拟测试详解

Kotlin Multiplatform:如何在 iOS 的单元测试中模拟对象

android中如何对一个包含调用数据库的activity进行单元测试啊?

扩展特征的单元测试类 - 我如何在特征中模拟和存根方法?

使用补丁模拟两个函数以进行单元测试