单元测试室和 LiveData [英] Unit testing Room and LiveData

查看:32
本文介绍了单元测试室和 LiveData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用新的 Android 架构组件.具体来说,我正在实现一个房间数据库,它在其查询之一上返回一个 LiveData 对象.插入和查询按预期工作,但是我在使用单元测试测试查询方法时遇到问题.

I'm currently developing an app using the newly Android Architecture Components. Specifically, I'm implementing a Room Database that returns a LiveData object on one of its queries. Insertion and querying work as expected, however I have an issue testing the query method using a unit test.

这是我要测试的 DAO:

Here is the DAO I'm trying to test:

NotificationDao.kt

@Dao
interface NotificationDao {

    @Insert
    fun insertNotifications(vararg notifications: Notification): List<Long>

    @Query("SELECT * FROM notifications")
    fun getNotifications(): LiveData<List<Notification>>
}

如您所知,查询函数返回一个 LiveData 对象,如果我将其更改为只是一个 ListCursor 或基本上无论如何我都会得到预期的结果,即插入数据库中的数据.

As you can tell, the query function returns a LiveData object, if I change this to be just a List, Cursor, or basically whatever then I get the expected result, which is the data inserted in the Database.

问题是下面的测试总是会失败,因为LiveData对象的value总是null:

The issue is that the following test will always fail because the value of the LiveData object is always null:

NotificationDaoTest.kt

lateinit var db: SosafeDatabase
lateinit var notificationDao: NotificationDao

@Before
fun setUp() {
    val context = InstrumentationRegistry.getTargetContext()
    db = Room.inMemoryDatabaseBuilder(context, SosafeDatabase::class.java).build()
    notificationDao = db.notificationDao()
}

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

@Test
fun getNotifications_IfNotificationsInserted_ReturnsAListOfNotifications() {
    val NUMBER_OF_NOTIFICATIONS = 5
    val notifications = Array(NUMBER_OF_NOTIFICATIONS, { i -> createTestNotification(i) })
    notificationDao.insertNotifications(*notifications)

    val liveData = notificationDao.getNotifications()
    val queriedNotifications = liveData.value
    if (queriedNotifications != null) {
        assertEquals(queriedNotifications.size, NUMBER_OF_NOTIFICATIONS)
    } else {
        fail()
    }
}

private fun createTestNotification(id: Int): Notification {
    //method omitted for brevity 
}

所以问题是:有没有人知道执行涉及 LiveData 对象的单元测试的更好方法?

推荐答案

Room 会在有观察者的情况下延迟计算 LiveData 的值.

Room calculates the LiveData's value lazily when there is an observer.

您可以查看示例应用.

它使用一个 getValue 实用方法,它添加了一个观察者来获取值:

It uses a getValue utility method which adds an observer to get the value:

public static <T> T getOrAwaitValue(final LiveData<T> liveData) throws InterruptedException {
    final Object[] data = new Object[1];
    final CountDownLatch latch = new CountDownLatch(1);
    Observer<T> observer = new Observer<T>() {
        @Override
        public void onChanged(@Nullable T o) {
            data[0] = o;
            latch.countDown();
            liveData.removeObserver(this);
        }
    };
    liveData.observeForever(observer);
    latch.await(2, TimeUnit.SECONDS);
    //noinspection unchecked
    return (T) data[0];
}

用 kotlin 更好,你可以把它变成一个扩展函数 :)

Better w/ kotlin, you can make it an extensions function :).

这篇关于单元测试室和 LiveData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆