单元测试室和 LiveData [英] Unit testing Room and 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
对象,如果我将其更改为只是一个 List
、Cursor
或基本上无论如何我都会得到预期的结果,即插入数据库中的数据.
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屋!