使用Realm的检测测试失败

时间:2016-10-27 09:30:55

标签: android mockito realm powermock android-testing

我正在实现一个检测测试来测试使用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. 

我该怎么办?

提前致谢

3 个答案:

答案 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。