当前位置: 首页 > 知识库问答 >
问题:

Android RxJava 2 JUnit测试-Android.os.looper中的getMainLooper未被模拟运行时异常

端木野
2023-03-14

尝试为使用Observeon(AndroidSchedulers.MainThread())的演示者运行JUnit测试时,遇到RuntimeException。

由于它们是纯JUnit测试,而不是Android instrumentation测试,因此它们没有访问Android依赖项的权限,导致我在执行测试时遇到以下错误:

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.<clinit>(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.<clinit>(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)
    …

共有1个答案

子车雅珺
2023-03-14

我们可以通过在测试运行之前用不同的调度程序初始化rxAndroidPlugins来避免这个问题。您可以在@BeforeClass方法中执行此操作,如下所示:

@BeforeClass
public static void setUpRxSchedulers() {
    Scheduler immediate = new Scheduler() {
        @Override
        public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
            // this prevents StackOverflowErrors when scheduling with a delay
            return super.scheduleDirect(run, 0, unit);
        }

        @Override
        public Worker createWorker() {
            return new ExecutorScheduler.ExecutorWorker(Runnable::run);
        }
    };

    RxJavaPlugins.setInitIoSchedulerHandler(scheduler -> immediate);
    RxJavaPlugins.setInitComputationSchedulerHandler(scheduler -> immediate);
    RxJavaPlugins.setInitNewThreadSchedulerHandler(scheduler -> immediate);
    RxJavaPlugins.setInitSingleSchedulerHandler(scheduler -> immediate);
    RxAndroidPlugins.setInitMainThreadSchedulerHandler(scheduler -> immediate);
}

或者您可以创建一个自定义的testrule,它将允许您跨多个测试类重用初始化逻辑。

public class RxImmediateSchedulerRule implements TestRule {
    private Scheduler immediate = new Scheduler() {
        @Override
        public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
            // this prevents StackOverflowErrors when scheduling with a delay
            return super.scheduleDirect(run, 0, unit);
        }

        @Override
        public Worker createWorker() {
            return new ExecutorScheduler.ExecutorWorker(Runnable::run);
        }
    };

    @Override
    public Statement apply(final Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                RxJavaPlugins.setInitIoSchedulerHandler(scheduler -> immediate);
                RxJavaPlugins.setInitComputationSchedulerHandler(scheduler -> immediate);
                RxJavaPlugins.setInitNewThreadSchedulerHandler(scheduler -> immediate);
                RxJavaPlugins.setInitSingleSchedulerHandler(scheduler -> immediate);
                RxAndroidPlugins.setInitMainThreadSchedulerHandler(scheduler -> immediate);

                try {
                    base.evaluate();
                } finally {
                    RxJavaPlugins.reset();
                    RxAndroidPlugins.reset();
                }
            }
        };
    }
}

然后可以将其应用于测试类

public class TestClass {
    @ClassRule public static final RxImmediateSchedulerRule schedulers = new RxImmediateSchedulerRule();

    @Test
    public void testStuff_stuffHappens() {
       ...
    }
}

来源:
https://www.infoq.com/articles/testing-rxjava2 https://medium.com/@peter.tackage/overriding-rxandroid-schedulers-in-rxjava-2-5561b3d14212

 类似资料:
  • 我遇到了一个挑战,当我单独运行测试时,测试通过了,但当我运行所有测试时,测试失败了,它会显示以下错误消息: java.lang.RuntimeException:Android.os.Looper中的方法getMainLooper未被嘲弄。详见http://g.co/androidstudio/not-mocked。 在Android.os.looper.GetMainLooper(looper.

  • TrendingViewModelTest 趋势视图模型 TrendingRepository: 在内部启动了一个Rxjava调用,它还挂钩到“AndroidSchedulers.MainThread()”,这可能是导致它的原因。

  • 我已经编写了示例CRUD方法,我已经为服务组件编写了JUnit测试用例,但得到的结果是“地址id没有找到…”当我做测试的时候。 @test public void updateAddressTest()引发ResourceNotFoundException{

  • 我在StackOverflow和Google上搜索了一段时间,试图找到能够在Spock规范中运行此代码的正确配置/语法: 然而,当我运行单元测试时,cglib向我抛出了一个令人讨厌的异常: 我看了这个问题/答案--用Stock中的GroovyMock或类似的方法模拟静态方法--希望它能给我一个好的起点,但是在我的例子中被模拟的类groovy.sql是一个groovy类,所以我不确定它是正确的起点。

  • 我使用Mickito模拟了一个postForObject resttemplate调用。 mockito.when(RestTemplate.PostForObject(mockito.eq(remoteServerlocation),mockito.any(Input.Class),mockito.eq(String.Class))).ThenReturn(responseString);

  • 问题内容: 在Eclipse中运行JUnit测试时出现此错误: 尽管我正在使用maven,但我尝试在类路径中添加库,而JUnit库位于POM依赖项中。 我已经尝试清理项目,并使用Eclipse的JUnit插件创建了一个新的JUnit测试用例,但仍然遇到相同的错误。 问题答案: 出现这种情况的原因是,使用时只有源代码正在编译(我使用的是maven 3.1.0,所以我不确定它是否始终如此)。 如果运行