在测试中将字段注入ViewModel

时间:2019-01-03 20:11:26

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

如果我编写测试,如何注入到 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>>)
    }
}

1 个答案:

答案 0 :(得分:1)

因为:

  1. lateinit var getAll: GetNotes(在MainViewModel中)是一个变量(不是方法)。
  2. MainViewModel以外的任何人都可以访问此变量lateinit var getAll: GetNotes
  3. 此变量是可变的。
  4. MainViewModel方法中的
  5. setUp()实例不是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的任何行为。