RxJava/RxAndroid의 비동기 테스트에서 "java.lang.Ex ceptionInitializaerError"가 발생했을 때...
java.lang.ExceptionInInitializerError
RxJava/RxAndroid의 비동기식 테스트를 쓸 때 "java.lang.Ex ceptionInitializerror"오류가 발생했습니다.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)
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.<clinit>(AndroidSchedulers.java:29)
... 41 more
까닭
잘 썼다고 생각하는 부분.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
에서.AndroidSchedulers.mainThread()
안드로이드가 의존하는 반을 이용했기 때문이다.
참조
https://stackoverflow.com/questions/43356314/android-rxjava-2-junit-test-getmainlooper-in-android-os-looper-not-mocked-runt
https://qiita.com/ko2ic/items/397fd147d4f3d0bdca09
대책
RxJavaPlagins/RxAndroid Plugins를 사용합니다.
테스트@Before
등에 다음 처리를 쓰면Scheduller를 지정하여 오류를 피할 수 있습니다.val immediate = object : Scheduler() {
override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
return super.scheduleDirect(run, 0, unit)
}
override fun createWorker(): Scheduler.Worker {
return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
}
}
RxJavaPlugins.setInitIoSchedulerHandler { immediate }
RxJavaPlugins.setInitComputationSchedulerHandler { immediate }
RxJavaPlugins.setInitNewThreadSchedulerHandler { immediate }
RxJavaPlugins.setInitSingleSchedulerHandler { immediate }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediate }
진일보한 문제
이러면 괜찮을 줄 알았는데 또 새로운 문제가 생겼군..
비동기 처리에 성공한 후에 비동기 처리를 계속하면 두 번째 비동기 처리는 영원히 끝나지 않는다.
(이 대책과 무관한 부분도 원인의 가능성을 부정할 수 없다...)
대책(2)
시험 때만.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
변경.subscribeOn(Schedulers.trampoline()).observeOn(Schedulers.trampoline())
.
Scheduller를 변경했으면 좋겠다는 생각입니다.
Drid Kaigi의 응용 프로그램을 보면 Repository는 프로젝트SchedulerProvider
를 하고 테스트 시 주입TestSchedulerProvider
을 한다.
https://github.com/DroidKaigi/conference-app-2018/blob/master/app/src/main/java/io/github/droidkaigi/confsched2018/data/repository/ContributorDataRepository.kt#L19
확실히 RxJavaPlagins/RxAndroid Plugins에서 변경하는 것은 약간의 흑마술감이 있기 때문에 DI로 바꾸는 것이 좋을 것 같다고 생각합니다.
결론
· Scheduller를 변경해야 합니다.
· DI로 Scheduller를 주입하여 테스트 시Schedulers.trampoline()
를 사용하는 것이 좋습니다.
Reference
이 문제에 관하여(RxJava/RxAndroid의 비동기 테스트에서 "java.lang.Ex ceptionInitializaerError"가 발생했을 때...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tsumuchan/items/f9656e5d0862dec0b543
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
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)
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.<clinit>(AndroidSchedulers.java:29)
... 41 more
잘 썼다고 생각하는 부분
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
에서.AndroidSchedulers.mainThread()
안드로이드가 의존하는 반을 이용했기 때문이다.참조
https://stackoverflow.com/questions/43356314/android-rxjava-2-junit-test-getmainlooper-in-android-os-looper-not-mocked-runt
https://qiita.com/ko2ic/items/397fd147d4f3d0bdca09
대책
RxJavaPlagins/RxAndroid Plugins를 사용합니다.
테스트@Before
등에 다음 처리를 쓰면Scheduller를 지정하여 오류를 피할 수 있습니다.val immediate = object : Scheduler() {
override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
return super.scheduleDirect(run, 0, unit)
}
override fun createWorker(): Scheduler.Worker {
return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
}
}
RxJavaPlugins.setInitIoSchedulerHandler { immediate }
RxJavaPlugins.setInitComputationSchedulerHandler { immediate }
RxJavaPlugins.setInitNewThreadSchedulerHandler { immediate }
RxJavaPlugins.setInitSingleSchedulerHandler { immediate }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediate }
진일보한 문제
이러면 괜찮을 줄 알았는데 또 새로운 문제가 생겼군..
비동기 처리에 성공한 후에 비동기 처리를 계속하면 두 번째 비동기 처리는 영원히 끝나지 않는다.
(이 대책과 무관한 부분도 원인의 가능성을 부정할 수 없다...)
대책(2)
시험 때만.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
변경.subscribeOn(Schedulers.trampoline()).observeOn(Schedulers.trampoline())
.
Scheduller를 변경했으면 좋겠다는 생각입니다.
Drid Kaigi의 응용 프로그램을 보면 Repository는 프로젝트SchedulerProvider
를 하고 테스트 시 주입TestSchedulerProvider
을 한다.
https://github.com/DroidKaigi/conference-app-2018/blob/master/app/src/main/java/io/github/droidkaigi/confsched2018/data/repository/ContributorDataRepository.kt#L19
확실히 RxJavaPlagins/RxAndroid Plugins에서 변경하는 것은 약간의 흑마술감이 있기 때문에 DI로 바꾸는 것이 좋을 것 같다고 생각합니다.
결론
· Scheduller를 변경해야 합니다.
· DI로 Scheduller를 주입하여 테스트 시Schedulers.trampoline()
를 사용하는 것이 좋습니다.
Reference
이 문제에 관하여(RxJava/RxAndroid의 비동기 테스트에서 "java.lang.Ex ceptionInitializaerError"가 발생했을 때...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tsumuchan/items/f9656e5d0862dec0b543
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
val immediate = object : Scheduler() {
override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
return super.scheduleDirect(run, 0, unit)
}
override fun createWorker(): Scheduler.Worker {
return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
}
}
RxJavaPlugins.setInitIoSchedulerHandler { immediate }
RxJavaPlugins.setInitComputationSchedulerHandler { immediate }
RxJavaPlugins.setInitNewThreadSchedulerHandler { immediate }
RxJavaPlugins.setInitSingleSchedulerHandler { immediate }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediate }
이러면 괜찮을 줄 알았는데 또 새로운 문제가 생겼군..
비동기 처리에 성공한 후에 비동기 처리를 계속하면 두 번째 비동기 처리는 영원히 끝나지 않는다.
(이 대책과 무관한 부분도 원인의 가능성을 부정할 수 없다...)
대책(2)
시험 때만.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
변경.subscribeOn(Schedulers.trampoline()).observeOn(Schedulers.trampoline())
.
Scheduller를 변경했으면 좋겠다는 생각입니다.
Drid Kaigi의 응용 프로그램을 보면 Repository는 프로젝트SchedulerProvider
를 하고 테스트 시 주입TestSchedulerProvider
을 한다.
https://github.com/DroidKaigi/conference-app-2018/blob/master/app/src/main/java/io/github/droidkaigi/confsched2018/data/repository/ContributorDataRepository.kt#L19
확실히 RxJavaPlagins/RxAndroid Plugins에서 변경하는 것은 약간의 흑마술감이 있기 때문에 DI로 바꾸는 것이 좋을 것 같다고 생각합니다.
결론
· Scheduller를 변경해야 합니다.
· DI로 Scheduller를 주입하여 테스트 시Schedulers.trampoline()
를 사용하는 것이 좋습니다.
Reference
이 문제에 관하여(RxJava/RxAndroid의 비동기 테스트에서 "java.lang.Ex ceptionInitializaerError"가 발생했을 때...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tsumuchan/items/f9656e5d0862dec0b543
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
· Scheduller를 변경해야 합니다.
· DI로 Scheduller를 주입하여 테스트 시
Schedulers.trampoline()
를 사용하는 것이 좋습니다.
Reference
이 문제에 관하여(RxJava/RxAndroid의 비동기 테스트에서 "java.lang.Ex ceptionInitializaerError"가 발생했을 때...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tsumuchan/items/f9656e5d0862dec0b543텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)