【问题标题】:IdlingResource Espresso with RxJavaIdlingResource Espresso 与 RxJava
【发布时间】:2018-09-04 15:48:57
【问题描述】:

我最近将我的应用程序从使用异步任务转换为 rxjava。现在,由于 espresso 没有 rxjava 的空闲资源,我的 espresso 测试不再等待我的数据调用完成。我注意到你可以制作自定义的空闲资源,但我不知道如何让它与 rxJava 调度程序一起工作,特别是 Scheduler.io。任何帮助/最佳实践将不胜感激。

【问题讨论】:

  • 为什么不使用简单的CountdownLatch 来等待一些外部事件?

标签: android rx-java android-espresso


【解决方案1】:

这是我解决问题的方法:

IdlingResource 实现:

public class IdlingApiServiceWrapper implements MyRestService, IdlingResource {

private final MyRestService           api;
private final AtomicInteger counter;
private final List<ResourceCallback> callbacks;

public IdlingApiServiceWrapper(MyRestService api) {
    this.api = api;
    this.callbacks = new ArrayList<>();
    this.counter = new AtomicInteger(0);
}

public Observable<MyData> loadData(){
    counter.incrementAndGet();
    return api.loadData().finallyDo(new Action0() {
        @Override
        public void call() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    counter.decrementAndGet();
                    notifyIdle();
                }
            });
        }
    });
}

@Override public String getName() {
    return this.getClass().getName();
}

@Override public boolean isIdleNow() {
    return counter.get() == 0;
}

@Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
    callbacks.add(resourceCallback);
}

private void notifyIdle() {
    if (counter.get() == 0) {
        for (ResourceCallback cb : callbacks) {
            cb.onTransitionToIdle();
        }
    }
   }
   }

这是我的测试:

public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity> {
@Inject
IdlingApiServiceWrapper idlingApiWrapper;

@Override
public void setUp() throws Exception {
    //object graph creation

    super.setUp();
    getActivity();
    Espresso.registerIdlingResources(idlingApiWrapper);
}

public void testClickOpenFirstSavedOffer() throws Exception {
    onData(is(instanceOf(DataItem.class)))
            .atPosition(0)
            .perform(click());
   }
  }

我使用Dagger 进行依赖注入。

【讨论】:

    【解决方案2】:

    编写了 RxJava 插件和 Espresso 之间的小集成。希望这对其他人有帮助。

    https://gist.github.com/digitalbuddha/d886eae1578bca78b9bf

    编辑:

    有一种更简单的方法可以完成这项任务。将以下规则添加到您的测试中

    public class AsyncTaskSchedulerRule implements TestRule {
        final Scheduler asyncTaskScheduler = Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);
    
        @Override
        public Statement apply(Statement base, Description description) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    RxJavaHooks.setOnIOScheduler(scheduler -> asyncTaskScheduler);
                    RxJavaHooks.setOnComputationScheduler(scheduler -> asyncTaskScheduler);
                    RxJavaHooks.setOnNewThreadScheduler(scheduler -> asyncTaskScheduler);
                    try {
                        base.evaluate();
                    } finally {
                        RxJavaHooks.reset();
                    }
                }
            };
        }
    }
    

    【讨论】:

    • 在尝试与您的示例类似的操作时遇到此错误:“java.lang.IllegalStateException: 另一种策略已注册:rx.plugins.RxJavaObservableExecutionHookDefault”如何避免这种情况?
    • 如果我没记错的话,在升级到 'io.reactivex:rxandroid:0.22.0' 之前我会遇到这个错误
    • 嗯...我目前使用的是 0.24,并确保我也依赖于最新的 RxJava。我很难找到合适的地方打电话给registerObservableExecutionHook()。看来测试setUp()已经来不及了。
    • base.evaluate/RxJavaHooks.reset() 有什么作用?当我删除该部分时,我的运气似乎更好。
    【解决方案3】:

    我目前正在使用这个实现。到目前为止,它对我来说更容易并且效果很好:https://github.com/rosshambrick/RxEspresso

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多