单元测试室和LiveData

单元测试室和LiveData

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

问题描述

我目前正在使用新的 Android体系结构组件.具体来说,我正在实现一个Room数据库,该数据库在其中一个查询中返回一个LiveData对象.插入和查询工作正常,但是使用单元测试测试查询方法时出现问题.

I'm currently developing an app using the newly Android Architecture Components. Specifically I'm implementing a Room Database that returns a LiveDataobject on one of it's queries. Insertion and querying works as expected, however I have an issue testing the query method using 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对象的单元测试吗?

推荐答案

当有观察者时,房间会懒惰地计算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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 20:30