根据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);
}
它可以按预期在App中运行,但是在进行测试时会变得有些棘手。我进行了以下测试(为了简单起见,对其进行了简化):
@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 page上阅读到,他们使用批注
@UiThreadTest
强制测试在UI线程上运行,据我所知,UI线程是一个looper线程,因此这应该可以解决我的问题。我补充说:@Rule
public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();
并更改了我的测试以包含注释
@Test
@UiThreadTest
public void testRealmExample() { ...}
这仍然会产生相同的异常。有人知道原因和解决方案吗?谢谢。
最佳答案
@UiThreadTest
实际上并没有使您处于工作的Looper线程,而只是使您可以访问UI元素。我必须承认,我还没有真正研究过为何存在这种差异的细节。我们正在对Looper线程使用自定义规则(这也会清理Realm实例)。您可以在这里看到它,也可以以此为灵感:
https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/rule/RunInLooperThread.java