我正在实现一个检测测试来测试使用Realm的Database Data Source类。所以现在我面临一些关于如何使用灯具以及如何模拟Realm的问题。 我的数据库数据源如下:
public class DatabaseDataSource {
private Realm realm;
public DatabaseDataSource(Realm realm) {
this.realm = realm;
}
public Observable<RealmResults> getContacts(String firstName, String lastName, String city, String zipCode) {
final RealmQuery realmQuery = realm.where(Contact.class);
if(!TextUtils.isEmpty(firstName)) {
realmQuery.contains("firstName", firstName);
}
if(!TextUtils.isEmpty(lastName)) {
realmQuery.contains("lastName", lastName));
}
if(!TextUtils.isEmpty(city)) {
realmQuery.contains("city", city);
}
if(!TextUtils.isEmpty(zipCode)) {
realmQuery.contains("zipCode", zipCode);
}
return realmQuery.findAll()
.asObservable();
}
}
我希望在我的模拟领域中有一个联系人列表,以便我可以检查过滤是否正常。我怎样才能做到这一点? 我试过了:
@RunWith(AndroidJUnit4.class)
public class DatabaseDataSourceTest extends BaseInstrumentedTest{
private DatabaseDataSource databaseDataSource;
private List<Contact> contacts;
@Before
public void setup() {
Realm.init(InstrumentationRegistry.getTargetContext());
Realm.setDefaultConfiguration(new RealmConfiguration.Builder().build());
databaseDataSource = new DatabaseDataSource(new DatabaseClient());
}
@Test
public void trial() throws Exception {
subscribeContactsListObservable(databaseDataSource.getContacts("firstName", null, null, null));
assertEquals(2, contacts.size());
}
private void subscribeContactsListObservable(final Observable<RealmResults> observable) {
notaries = null;
observable.map(new Func1<RealmResults, List<Contact>>() {
@Override
public List<Notary> call(RealmResults realmResults) {
return realmResults != null? new ArrayList<>(realmResults) : null;
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Contact>>() {
@Override
public void onCompleted() {
contacts = null;
}
@Override
public void onError(Throwable e) {
contacts = null;
}
@Override
public void onNext(List<Contact> contactsList) {
contacts = contactsList;
}
});
}
}
但是当使用以下异常执行Observable.subscribe时测试失败:
You can't register a listener from a non-Looper thread or IntentService thread.
我该怎么办?
提前致谢
答案 0 :(得分:1)
那么它会在该错误消息中明确告诉您问题的解决方案:
You can't register a listener from **a non-Looper thread** or IntentService thread.
这是因为asObservable()
需要注册RealmChangeListener
才能收听领域的变化。
检测线程是非looper线程,因此这意味着您无法收听其中的更改。
解决方案,你需要使用一个Looper线程(比如主线程),或者创建一个Looper线程,并在该looper线程中创建Realm实例。方便的是,RxAndroid有一个所谓的LooperScheduler,您可以使用AndroidSchedulers.from(Looper)创建它,它允许您在任意looper线程上执行逻辑。
有可能研究Realm already tests their looper-related stuff with this RunInLooperThread test rule。
答案 1 :(得分:0)
显然,您的getContacts()
方法在非looper后台线程上运行,该线程不适用于我们的更改侦听器(因此我们的asObservable()
方法)。
您可以改为创建observable,但请记住,它会一次性发出列表然后完成。对于连续更新,您需要使用Looper线程。
return Observable.just(realmQuery.findAll());
答案 2 :(得分:0)
这是我的一个测试的片段:
public class PlaybackDatabaseTest extends ApplicationTestCase<Application> {
public PlaybackDao dao;
public PlaybackDatabaseTest(){ super(Application.class);}
@Override
protected void setUp() throws Exception {
super.setUp();
DatabaseModule module = new DatabaseModule();
RealmConfiguration config = module.providePlaybackRealmConfiguration(getContext());
dao = module.providePlaybackDatabase(config);
}
public void testAddingPlaylistAndDeletingDatabase() {
dao.purgeDatabase();
int id1 = 0;
Playlist playlist = createTestPlaylist(id1, 0, 100);
dao.addPlaylist(playlist);
boolean exist1 = dao.isPlaylistExist(String.valueOf(id1));
assertTrue(exist1);
dao.purgeDatabase();
exist1 = dao.isPlaylistExist(String.valueOf(id1));
assertFalse(exist1);
}
}
但是,它使用Dagger2来创建数据库'数据访问对象'。
Realm可以从主线程工作,使用Observable.toblocking()这样你的 测试线程将一直等到jub完成。
Realm使用Android的Handler进行并发(.map(),。flatt()运算符默认返回Schedulers.computation()上的结果),因此要解决Handler问题,请使用ApplicationTestCase。