我在使用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());
没有任何事情发生,我尝试了几种调度程序组合,没有工作。关于我做错了什么的任何想法。考试 最终成功运行但显然应该崩溃这些断言。
答案 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();
}
});
}
...
我愿意接受任何更好的解决方案。