使用RxJava测试Android Realm时出现“opened from a thread without a Looper”异常

7
我有以下代码,基于Realm提供的文档(https://realm.io/docs/java/latest/#rxjava
public Observable<Foo> getFooById(String id) {

    realm = Realm.getInstance(realmConfiguration);

    return realm.where(Foo.class)
            .equalTo("id", id)
            .findFirstAsync()
            .asObservable()
            .filter(this::filterResult);
}

这在应用程序中按预期工作,但当涉及测试时就会变得棘手一些。我有以下测试(简化以保持简单):
@Test
public void testRealmExample() {

    RealmConfiguration config = new RealmConfiguration.Builder(context)
            .name("test.realm")
            .inMemory()
            .build();

    DataManager dataManager = new DataManager(config);

    TestSubscriber<Foo> testSubscriber = new TestSubscriber<>();
    dataManager.getFoo("").observeOn(AndroidSchedulers.mainThread()).subscribe(testSubscriber);
    testSubscriber.assertNoErrors();
}

执行测试时发生以下错误:java.lang.IllegalStateException: Your Realm is opened from a thread without a Looper. Async queries need a Handler to send results of your query
为了解决这个问题,我在Realm GitHub 页面上阅读到他们使用了一个注释@UiThreadTest来强制将测试运行在UI线程上。根据我的理解,UI线程是一个looper线程,因此这应该可以解决我的问题。我添加了以下代码:
@Rule
public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();

我将我的测试更改为包括注释。

@Test
@UiThreadTest
public void testRealmExample() { ...}

这仍然导致相同的异常。有人知道原因和解决方案吗?谢谢。
1个回答

0

谢谢!那这些测试是怎么通过的呢?特别是 findFirstAsync_emittedOnSubscribe,因为它和我所做的几乎一模一样。https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/RxJavaTests.java - Graham Smith
我怀疑在单元测试期间AndroidSchedulers.mainThread实际上是无效的。您可以看到,在我们的测试中,我们只是在默认线程上进行观察。这只是一个猜测,我还没有测试过它。 - Christian Melchior
谢谢你的帮助,我想现在我会扩展我们的 Realm 测试工具应用程序来运行我想要运行的测试的等效部分。这样会更容易,而且我们仍然可以获得覆盖率。Realm很棒,但单元测试似乎相当困难,这是路线图上的事情吗? - Graham Smith
1
是的,现在我们正在考虑添加Robolectric支持,并希望在未来能够提供标准的JUnit4支持。 - Christian Melchior
1
只有一件事:在测试中替换您的调度程序。请参阅 Alexis MasFederico Paolinelli 的帖子以了解如何进行该操作。 - Wolfram Rittmeyer
一整天都在寻找这个答案,谢谢! - Jeff Jones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接