【问题标题】:Inject fields into ViewModel in tests在测试中将字段注入 ViewModel
【发布时间】:2019-01-03 20:11:26
【问题描述】:

如果我编写测试,如何注入 ViewModel。我收到错误UninitializedPropertyAccessException: lateinit property getAll has not been initialized。我想测试从远程 API 获取数据。我是编写单元测试的新手,所以我想了解在这种情况下如何编写它。

class MainViewModel @Inject constructor(
    private val commandProcessor: CommandProcessor,
    private val app: Application
) : AndroidViewModel(app), CoroutineScope {
    var job: Job = Job()
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.IO + job

    private var notesList: LiveData<List<Note>>? = null
    private var editedNote: LiveData<Note>? = null
    @Inject lateinit var getAll: GetNotes
    @Inject lateinit var add: AddNote

    private fun fetchNotes() {
        getAll.execute()
        notesList = getAll.result
    }

    fun getNotes(): LiveData<List<Note>>? {
        if (notesList == null) fetchNotes()
        return notesList
    }

    override fun onCleared() {
        super.onCleared()
        job.cancel()
        val commands = arrayListOf(getAll, add, delete, getSingle, edit)
        commands.forEach { it.cancelJob() }
    }
}

测试样本:

@RunWith(MockitoJUnitRunner::class)
class MainViewModelTest {
    private lateinit var viewModel: MainViewModel
    val app: Application = mock()
    @Inject lateinit var getAllMock: GetNotes

    @Before
    fun setUp() {
        viewModel = MainViewModel(CommandProcessor(), app)
        Mockito.`when`(viewModel.getAll).thenReturn(getAllMock)
    }

    @Test
    fun testGetNotes() {
        val livedata = MutableLiveData<List<Note>>()
        Mockito.`when`(getAllMock.result).thenReturn(livedata)
        assert(viewModel.getNotes() is LiveData<List<Note>>)
    }
}

【问题讨论】:

    标签: android unit-testing kotlin mockito dagger-2


    【解决方案1】:

    因为:

    1. lateinit var getAll: GetNotes(在 MainViewModel 中)是一个变量(不是方法)。
    2. MainViewModel 之外的任何其他人都可以访问此变量lateinit var getAll: GetNotes
    3. 此变量是可变的。
    4. MainViewModelsetUp() 方法中的实例不是Mockito.mock(MainViewModel::class.java) 的真实模拟实例

    然后:要测试MainViewModel 中的逻辑,我们可以创建MainViewModel 实例并简单地在setUp() 方法中设置该变量。

    private lateinit var mockGetAll: GetNotes
    
    @Before
    fun setUp() {
        mockGetAll = mock(GetNotes::class.java)
        viewModel = MainViewModel(CommandProcessor(), app).apply {
            getAll = mockGetAll
        }
    }
    

    在此之后,我们可以模拟 mockGetAll: GetNotes 的任何行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      • 2013-05-01
      • 2017-05-20
      相关资源
      最近更新 更多