Building Done, I used Android Architecture Components, Data Binding and Room. Inevitably, while writing tests I found myself needing to assert on code that’s called inside a
LiveData observer, in its
While easy, the fix wasn’t obvious, and even after Googling, the answer wasn’t readily available so I’m posting it here to help future users of
LiveData itself doesn’t provide a
setValue() method, the first step is to create a
MutableLiveData object in your tests, pass it to your mock/fake
LiveData provider (for example, if you’re using Room this is your mock
Dao), and then continue happily asserting on calls made in
Try that though and you’re greeted with this crash:
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.at android.os.Looper.getMainLooper(Looper.java)
Which is descriptive enough but all it really says is that you are doomed if you’re trying to
setValue() while running plain Java unit tests.
No need to fret as it turns out you can still use this method to test your LiveData observers!
- First, add this dependency in your module’s build.gradle file:
Make sure you use the same version as the rest of your
- Then, in the test class where you need to call
setValue()and assert, add this field:
@Rulepublic TestRule rule = new InstantTaskExecutorRule();
Behind the scenes, this bypasses the main thread check, and immediately runs any tasks on your test thread, allowing for immediate and predictable calls and therefore assertions.
I hope this helps more folks avoid getting stuck on this as it has been a major annoyance during my experiments with the otherwise straightforward Android Components library.
Download Done to see the resulting app!