androidTest 中的 Android LiveData 返回 null

标签 android kotlin android-room android-architecture-components android-livedata

我正在运行 androidTest 仪器测试,我有一个方法可以使用 Room 从 DAO 对象返回 LiveData。

我是这样调用方法的:

val animal = roomDatabase.animalsDao().getAnimal(1)
animal.observeForever(mMockObserver)
assertNotNull(animal.value)

我使用 Mockito 来模拟观察者:

@Mock
private lateinit var mMockObserver = Observer<Animal>

这应该返回一个包含 ID 为 1 的 Animal 的 LiveData 实例,但它是 null。据我了解,为了让 LiveData 返回任何内容,必须有一个观察者。我是否设置不正确?

注意:如果我在 DAO 中更改 getAnimal() 的签名以直接返回 Animal 而不是 LiveData,那么它会起作用,所以我知道它与 LiveData 有关。

最佳答案

经过更多挖掘后,我发现了 Google 通过 GitHub 上的架构组件示例提供的实用方法。

LiveDataTestUtil

public class LiveDataTestUtil {

    /**
     * Get the value from a LiveData object. We're waiting for LiveData to emit, for 2 seconds.
     * Once we got a notification via onChanged, we stop observing.
     */
    public static <T> T getValue(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];
    }
}

这允许您传递 LiveData 实例并取回它持有的值。

更新(JUnit 4):

您还可以使用 InstantTaskExecutorRule结合 observeForever测试您的 LiveData。在 Kotlin 中,您在测试类的顶部设置 @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() 以确保同步处理 LiveData,然后在您的测试用例中 myLiveData.observeForever {/* Do事件发出时发生的事情 */ 以获取 LiveData 值。

更新(JUnit 5)

如果您使用的是 JUnit5,那么您可以使用此扩展来代替上面更新 (JUnit4) 中解释的规则。

class InstantTaskExecutorExtension : BeforeEachCallback, AfterEachCallback {

    override fun beforeEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
            override fun executeOnDiskIO(runnable: Runnable) {
                runnable.run()
            }

            override fun postToMainThread(runnable: Runnable) {
                runnable.run()
            }

            override fun isMainThread(): Boolean {
                return true
            }
        })
    }

    override fun afterEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(null)
    }
}

通过像这样注释您的测试类来使用此扩展:

@ExtendWith(InstantTaskExecutorExtension::class)
class MyTestClass { ... }

如果您不熟悉扩展(它们取代了 JUnit 4 规则),您可以在此处找到其他文档:https://junit.org/junit5/docs/current/user-guide/#extensions

关于androidTest 中的 Android LiveData 返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48602979/

相关文章:

Android 设置日期选择器最小日期

android - Kotlin 和 Anko 协程 : return outside async

android - 房间多表同对象(多语言数据库)

android - 如何将 Android SqLite 数据库从内部存储迁移到 Room?

java - 如何从Android Room中的多个数据库中进行选择(How to attach databases)

android - 如何获得可用的网络运营商? (使用 RIL 和非 API 方法)

android - Cordova 4.0 Linear-Gradient 颜色 CSS3 不适用于 Android 设备

kotlin - Vaadin 12,javaScript:java.lang.IllegalArgumentException:无法将类java.util.HashMap编码为json

generics - 函数返回值的Kotlin默认泛型参数

android - 通过多个 Activity 传递数据