Testing LiveData on Android
Tags: kotlin, android, testing, programming
Published: 2019-03-17 15:31:20

---
title: Testing LiveData on Android
published: true
description: Testing LiveData represents an interesting challenge due to the peculiarities of its technology and the way it eases development for your Android app.
tags: kotlin,android,testing,programming
cover_image: https://alediaferia.com/wp-content/uploads/2018/12/irvan-smith-563895-unsplash.jpg
canonical_url: https://alediaferia.com/2018/12/17/testing-livedata-room-android/
---

_Originally published on [alediaferia.com](https://alediaferia.com/2018/12/17/testing-livedata-room-android/)_

I’ve recently started to build an Android app to keep motivated on my journey to learn [Kotlin](https://kotlinlang.org/). My most recent experience has been with [Architecture Components](https://developer.android.com/topic/libraries/architecture/) and this brief blog post, in particular, will focus on unit testing your DAO when using [`LiveData`](https://developer.android.com/jetpack/arch/livedata).

# What is LiveData?

`LiveData` is a lifecycle-aware, observable data holder that will help you react to changes in you data source. In my case, I’m using it in combination with [`Room`](https://developer.android.com/jetpack/arch/room) to make sure my app reacts to the new data becoming available in my database.

# Our simple DAO
For this blog post let’s just pretend we have a very simple DAO that looks like the following:

```kotlin
@Dao
interface PostDao {
    @Query("SELECT * from posts")
    fun getAll(): LiveData<List<Post>>
    
    @Insert
    fun insert(post: Post)
}
```

This is just a DAO that helps you fetch posts.

As you can see, the return type for the function is not just a plain `List<Post>` but it wraps it in a [`LiveData`](https://developer.android.com/reference/android/arch/lifecycle/LiveData) instance. This is great because we can get an instance of our list of posts once and then [_observe_ for changes and react to them](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html#observe(android.arch.lifecycle.LifecycleOwner,%20android.arch.lifecycle.Observer%3CT%3E)).

# Let's test it

The Android Developer documentation has a neat example on how to unit test your DAO:

```kotlin
@RunWith(AndroidJUnit4::class)
class PostDaoReadWriteTest {
    private lateinit var postDao: PostDao
    private lateinit var db: TestDatabase

    @Before
    fun createDb() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        db = Room.inMemoryDatabaseBuilder(
                context, TestDatabase::class.java).build()
        postDao = db.getPostDao()
    }

    @After
    @Throws(IOException::class)
    fun closeDb() {
        db.close()
    }

    @Test
    @Throws(Exception::class)
    fun writePostAndReadInList() {
        assertEquals(0, postDao.getAll().value?.size)
        val post = TestUtil.createPost(id=42)
        postDao.insert(post)
        assertEquals(1, posttDao.getAll().value?.size)
    }
}
```

This pretty simple test has the aim of testing that the data is being exposed correctly and that, once the post is added to the database, it is reflected by the `getAll()` invocation.

Unfortunately, by the time we are asserting on it, the value of the `LiveData` instance will not be populated and will make our test fail. This is because `LiveData` uses a lifecycle-oriented asynchronous mechanism to populate the underlying data and expects an observer to be registered in order to inform about data changes.

## _Observe_ the data

`LiveData` offers a convenient observe method that allows for observing the data as it changes. We can use it to register an observer that will assert on the expected value.

The [`observe`](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html#observe(android.arch.lifecycle.LifecycleOwner,%20android.arch.lifecycle.Observer%3CT%3E)) method has the following signature:

```java
void observe(LifecycleOwner owner, Observer<T> observer)
```

It expects an [`observer`](https://developer.android.com/reference/android/arch/lifecycle/Observer.html) instance and the [`owner`](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html) for its life-cycle. In our case, we’re only interested in keeping the observer around just enough to be able to assert on the changed data. We don’t want the same assertion to be evaluated every time the data changes.

## Own your lifecycle
What we can do, then, is build an observer instance that owns its own life-cycle. After handling the [`onChange`](https://developer.android.com/reference/android/arch/lifecycle/Observer.html#onChanged(T)) event we will mark the observer life-cycle as destroyed and let the framework do the rest.

Let’s see what the observer code looks like:

```kotlin
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.Observer

/**
 * Observer implementation that owns its lifecycle and achieves a one-time only observation
 * by marking it as destroyed once the onChange handler is executed.
 *
 * @param handler the handler to execute on change.
 */
class OneTimeObserver<T>(private val handler: (T) -> Unit) : Observer<T>, LifecycleOwner {
    private val lifecycle = LifecycleRegistry(this)
    init {
        lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
    }

    override fun getLifecycle(): Lifecycle = lifecycle

    override fun onChanged(t: T) {
        handler(t)
        lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    }
}
```

This observer implementation accepts a _lambda_ that will be executed as part of the `onChange` event. As soon as the handler is complete, its own lifecycle will proceed to mark itself as `ON_DESTROY` which will trigger the removal process from the `LiveData` instance.

We can then create an extension on LiveData to leverage this kind of observer:
```kotlin
fun <T> LiveData<T>.observeOnce(onChangeHandler: (T) -> Unit) { 
    val observer = OneTimeObserver(handler = onChangeHandler) 
    observe(observer, observer)
}
```

# Time to fix our test

```kotlin
@RunWith(AndroidJUnit4::class)
class PostDaoReadWriteTest {
    private lateinit var postDao: PostDao
    private lateinit var db: TestDatabase
  
    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    @Before
    fun createDb() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        db = Room.inMemoryDatabaseBuilder(
                context, TestDatabase::class.java).build()
        postDao = db.getPostDao()
    }

    @After
    @Throws(IOException::class)
    fun closeDb() {
        db.close()
    }

    @Test
    @Throws(Exception::class)
    fun writePostAndReadInList() {
        postDao.getAll().observeOnce {
          assertEquals(0, it.size)
        }
      
        val post = TestUtil.createPost(id=42)
        postDao.insert(post)
      
        postDao.getAll().observeOnce {
          assertEquals(1, it.size)
        }
    }
}
```

A couple of things to notice this time.

First of all, we’re taking advantage of an [`InstantTaskExecutorRule`](https://developer.android.com/reference/androidx/arch/core/executor/testing/InstantTaskExecutorRule). This is a helpful utility rule that takes care of swapping the background asynchronous task executor with a synchronous one. This is vital to be able to deterministically test our code. _(Check [this](https://github.com/junit-team/junit4/wiki/rules) out if you wanna know more about JUnit rules)_.

In addition to that, we’re now leveraging the `LiveData` extension that we have written to write our assertions:

```kotlin
postDao.getAll().observeOnce {
    assertEquals(0, it.size)
}
```

We have just asserted in a much more compact and expressive way by leaving all the details inside our observer implementation. We are now asserting on the `LiveData` instance deterministically, making this kind of tests easier to read and write.

# Conclusion
I hope this post will help you write tests for your DAO more effectively. This is one of my earliest experiences with Kotlin and Android: please, feel free to comment with better approaches to solve this.

###### Cover photo by [Irvan Smith](https://unsplash.com/photos/cwqG1N1AtI0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/mobile-app-programming?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

_Originally published on [alediaferia.com](https://alediaferia.com/2018/12/17/testing-livedata-room-android/)_