Unit Test a ViewModel logic with Cloud Firestore operations.
I struggled for a while, trying to unit test the logic of my ViewModel when I had some Cloud Firestore operations to do. How to mock the result of my query? How to tell my tests to wait for the “onSucceedListener” to emit?
I didn’t like the whole listener logic making my code ugly, heavy and hard to test…
I used to have something like that:
And try to do a fake Task class in my test but it was heavy and complicated and didn’t work for all kind of task.
So I look into how to take advantage of the Kotlin Coroutines to wait for the result of my task to be here without blocking the UI.
This article explain how to convert your Firestore tasks into suspend functions you can execute in your View Model and unit test them easily.
We assume that the reader has basic understanding of coroutine functions, MVVM architecture and unit test.
Our application can create and get an object User from the Cloud Firestore database.
Your project should be in Kotlin and you should have the following dependencies
The User Object
It’s a simple data class with a couple of attributes:
Sealed class to hold the result
The sealed class Result holds the result of the Firestore operation and its status (Success, Error, Canceled). It allows us to know if our operation succeed or not and get the eventual error message Firestore returns.
Create a Coroutine from a Firestore Task
We now need to convert our Firestore Task into a coroutine function that will wait for the answer of the query and emit a Result object with the corresponding data.
We simply create an extension for Task object, await(), that will return:
- Result.Success with the data if the query was successful
- Result.Error with the corresponding error message if an error happened
- Result.Canceled with an eventual error message if the query was canceled.
This code was took and modified from: https://github.com/Kotlin/kotlinx.coroutines
Repository, Fake and Implementation
In order to test the actions of our repository easily, we declare all the methods of our repository in an interface then to do an implementation for our application with the real Firestore queries and a fake repository for our test that sends fake results.
User Repository Interface:
User Repository Implementation:
Fake User Reposiory for Unit test:
The ViewModel implementation
The ViewModel now looks like this:
It executes the coroutines function defined in the repository, wait for the result and emit the data corresponding (user information or a message).
The view can simply subscribes to those Live Data to update the UI.
I didn’t write the view implementation. A lot of tutorial are available online to learn more about MVVM architecture and Live Data in Android.
The ViewModel tests:
It’s now time to test our ViewModel logic.
In order to make testing easier I have created a couple of helpers:
- LiveDataTestUtil: used to test a LiveData, it wait for the result to be emitted then gets its value
- A variable testUser: generates a User with its data.
I can then simply write my unit test by executing my ViewModel methods and use assertEquals to verify that the Live Data emitted have the right values:
Here’s the best solution I found to unit test my ViewModel with Firestore operations. Please let me know what you think and share you way to do it.








