RxJava:断言不起作用

时间:2017-01-31 17:56:48

标签: android unit-testing rx-java

我在使用Robolectric进行编码的单元测试中遇到了一些问题。问题是我正在测试一个UseCase,这个UseCase使用rx.Observable来执行异步任务,内部它还调用另一个rx.Observable来排序非常大的集合。我在UseCase中注入了Schedulers,我尝试使用Schedulers.immediate()new TestSceduler()AndroidSchedulers.mainThread()。似乎没什么用。这是执行流程:

...
@Test
public void testCacheConsistency() {
    AppComponent appComponent = getAppComponents(new EventList1MockRepository());
    injectFields(appComponent);

    //First we are going to request a list of events without using the cache
    getEventsInteractor.execute(new GetEvents.Callback() {
        @Override
        public void onEventsFetched(List<Event> eventList) {
            assertTrue(false); //This asserts should throw an exception
            assertEquals(42343, eventList.size());
        }

        @Override
        public void onCachedEventsFetched(List<Event> eventList) {
            assertFalse("This method shouldn't be called", true);
        }

        @Override
        public void onErrorFetchingEvents(String error) {
            assertFalse("This method shouldn't be called", true);
        }

        @Override
        public void onErrorFetchingCachedEvents(String message) {
            assertFalse("This method shouldn't be called", true);
        }
    }, false);
    ...
}
...

首先调用测试。 insde GetEventsInteractor #execute方法我这样做:

...
mRepository.getEvents(new BaseApiResponse<List<ApiEventResponse>>() {
        @Override
        public void onError(String error) {
            callback.onErrorFetchingEvents(error);
        }

        @Override
        public void onResponse(List<ApiEventResponse> apiResponse) {

            mapEventResponse(apiResponse)
                    .subscribe(new Subscriber<List<Event>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(List<Event> items) {
                    mScheduleDbCache.setSchedules(mGetUserSipid.get(), items);
                    mScheduleMemoryCache.setSchedules(mGetUserSipid.get(),items);

                    callback.onEventsFetched(items);
                    onCompleted();
                }
            });
        }
        ...
}
...

我要排序一个非常大的列表。 mapEventResponses方法负责在rx.Observable中对该列表进行排序。

private Observable<List<Event>> mapEventResponse(final List<ApiEventResponse> apiResponse) {

    return Observable.create(new Observable.OnSubscribe<List<Event>>() {
        @Override
        public void call(final Subscriber<? super List<Event>> subscriber) {
            List<Event> items = new ArrayList<>();
            if (apiResponse != null) {
                for (ApiEventResponse obj : apiResponse) {
                    if (obj == null) continue;
                    items.add(EventMapper.transform(obj));
                }
            }
            Collections.sort(items, new Comparator<Event>() {
                public int compare(Event ev1, Event ev2) {
                    return ev1.getmStartTs().compareToIgnoreCase(ev2.getmStartTs());
                }
            });

            subscriber.onNext(items);
        }
    }).subscribeOn(mBackgroundScheduler).observeOn(mMainScheduler);
}

这是方法,我认为mBacgroundSceduler和mMainScheduler是正确注入的。

此测试用例中的每一步都完美执行,问题是当我到达资产时:

assertTrue(false); //This asserts should throw an exception
assertEquals(42343, eventList.size());

没有任何事情发生,我尝试了几种调度程序组合,没有工作。关于我做错了什么的任何想法。考试 最终成功运行但显然应该崩溃这些断言。

1 个答案:

答案 0 :(得分:0)

正如@Eugen Martynov所指出的那样,问题是我在调用rx.Observable方法时返回的mapEventResponse()正在捕获AssertException并且它已经死了。我找到的一个解决方法是创建ExceptionSubscriber类:

public abstract class ExceptionSubscriber<T> extends rx.Subscriber<T> {

    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {
        throw new RuntimeException(e);
    }

    @Override
    public void onNext(T t) {

    }
}

然后由AssertException行生成的assertTrue(false);它被正确传播和处理。

例如:

    mRepository.getEvents(new BaseApiResponse<List<ApiEventResponse>>() {
        @Override
        public void onError(String error) {
            callback.onErrorFetchingEvents(error);
        }

        @Override
        public void onResponse(List<ApiEventResponse> apiResponse) {

            mapEventResponse(apiResponse).subscribe(new ExceptionSubscriber<List<Event>>() {
                @Override
                public void onNext(List<Event> items) {
                    mScheduleDbCache.setSchedules(mGetUserSipid.get(), items);
                    mScheduleMemoryCache.setSchedules(mGetUserSipid.get(),items);

                    callback.onEventsFetched(items);
                    onCompleted();
                }
            });
        }
        ...

我愿意接受任何更好的解决方案。