Rxjava2 유닛 테스트 출현: Android RxJava2 JUnit test - getMainLooper in android.os.Looper not mocked RuntimeException
Android RxJava 2 JUnit test - getMainLooper in android.os.Looper not mocked RuntimeException
java.lang.ExceptionInInitializerError
at io.reactivex.android.schedulers.AndroidSchedulers$1.call(AndroidSchedulers.java:35)
at io.reactivex.android.schedulers.AndroidSchedulers$1.call(AndroidSchedulers.java:33)
at io.reactivex.android.plugins.RxAndroidPlugins.callRequireNonNull(RxAndroidPlugins.java:70)
at io.reactivex.android.plugins.RxAndroidPlugins.initMainThreadScheduler(RxAndroidPlugins.java:40)
at io.reactivex.android.schedulers.AndroidSchedulers.(AndroidSchedulers.java:32)
…
Caused by: java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.os.Looper.getMainLooper(Looper.java)
at io.reactivex.android.schedulers.AndroidSchedulers$MainHolder.(AndroidSchedulers.java:29)
...
java.lang.NoClassDefFoundError: Could not initialize class io.reactivex.android.schedulers.AndroidSchedulers
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
이 문제가 발생한 이유는
AndroidSchedulers.mainThread
가 LooperScheduler
의 실례로 되돌아왔지만 LooperScheduler
는 안드로이드에 의존하여 순수한 자바의 단원 테스트에서 사용할 수 없기 때문이다.문제의 원인을 찾으면 해결하기가 훨씬 쉽다.단원 테스트가 실행되기 전에 안드로이드에 의존하지 않는 RxAndroidPlugins
을 초기화해야 합니다.다음은 두 가지 해결 방안을 제시한다.시나리오 1:
Scheduler
에서 초기화@BeforeClass
:@BeforeClass
public static void setUpRxSchedulers(){
final Scheduler immediate = new Scheduler() {
@Override
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
return super.scheduleDirect(run, 0, unit);
}
@Override
public Worker createWorker() {
return new ExecutorScheduler.ExecutorWorker(new Executor() {
@Override
public void execute(@android.support.annotation.NonNull Runnable command) {
command.run();
}
});
}
};
RxJavaPlugins.setInitIoSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitComputationSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitNewThreadSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitSingleSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxAndroidPlugins.setInitMainThreadSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
}
이렇게 하면 문제를 해결할 수 있지만 모든 테스트 클래스에 이런 코드를 추가해야 합니다. 매우 번거롭습니다. 간단한 방법이 있습니까?물론 있습니다. 우리는 사용자 정의
Scheduler
를 할 수 있고 필요한 곳에서 직접 호출하면 됩니다.시나리오 2:
사용자 정의
TestRule
를 통해 구현RxSchedulersOverrideRule
:public class RxSchedulersOverrideRule implements TestRule {
private Scheduler immediate = new Scheduler() {
@Override
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
return super.scheduleDirect(run, 0, unit);
}
@Override
public Worker createWorker() {
return new ExecutorScheduler.ExecutorWorker(new Executor() {
@Override
public void execute(@android.support.annotation.NonNull Runnable command) {
command.run();
}
});
}
};
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
RxJavaPlugins.setInitIoSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitComputationSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitNewThreadSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxJavaPlugins.setInitSingleSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
RxAndroidPlugins.setInitMainThreadSchedulerHandler(new Function, Scheduler>() {
@Override
public Scheduler apply(@NonNull Callable schedulerCallable) throws Exception {
return immediate;
}
});
try {
base.evaluate();
}finally {
RxJavaPlugins.reset();
RxAndroidPlugins.reset();
}
}
};
}
}
필요한 경우 다음과 같이 직접 호출하면 됩니다.
@ClassRule
public static RxSchedulersOverrideRule sSchedulersOverrideRule = new RxSchedulersOverrideRule();
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.