Reputation: 1583
How to inject into ViewModel if I write tests. I get error UninitializedPropertyAccessException: lateinit property getAll has not been initialized
. I would like to test fetching data from remote API. I am new to writing unit tests so I want to find out how to write it in this case.
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() }
}
}
Test sample:
@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>>)
}
}
Upvotes: 1
Views: 1456
Reputation: 72
Because:
lateinit var getAll: GetNotes
(in MainViewModel
) is a variable (not a method).MainViewModel
can access this variable lateinit var getAll: GetNotes
.MainViewModel
instance in setUp()
method is not a real mock instance by Mockito.mock(MainViewModel::class.java)
Then: To test logic in MainViewModel
, we can create MainViewModel
instance and simply set that variable in setUp()
method.
private lateinit var mockGetAll: GetNotes
@Before
fun setUp() {
mockGetAll = mock(GetNotes::class.java)
viewModel = MainViewModel(CommandProcessor(), app).apply {
getAll = mockGetAll
}
}
After this, we can mock any behaviours for our mockGetAll: GetNotes
.
Upvotes: 3