但是,这个模拟还有其他交互:

时间:2017-01-13 12:43:30

标签: android unit-testing rx-java retrofit2 mvp

所以我有问题,这是我的演示者代码:

@Override
public void login(String phone, String password) {
    loginView.showProgress();
    compositeSubscription.clear();

    Subscription subscription = service.login(phone,password)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(data -> {
                //Log.d("Login", new Gson().toJson(data));
                loginView.hideProgress();
                if(data.getSt()==1)
                {
                    saveDataPartner(data.getData().getId_hos(), data.getData().getName(), data.getData().getEmail(), data.getData().getPhone(), data.getData().getAvatar());
                    loginView.navigateToMainMenu();
                }
                else {
                    loginView.showMessage(data.getMsg());
                }
            }, error -> {
                loginView.hideProgress();
                loginView.showMessage(ErrorUtils.getErrorMessage(error));
            });
}

我想用这段代码测试一下:

@Before
public void setUp() throws Exception {
    RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {
        @Override
        public Scheduler getMainThreadScheduler() {
            return Schedulers.immediate();
        }
    });
}

@After
public void tearDown() {
    RxAndroidPlugins.getInstance().reset();
}

@Test
public void clickBtnLogin() {

    User user = new User();
    user.setName("aa");
    ResultAPIUser<User> ru = new ResultAPIUser<User>();

    ru.setData(user);
    ru.setMsg("example message");
    ru.setSt(1);

    when(service.login("aa","aa")).thenReturn(Observable.just(ru));

    loginPresenter.login("aa","aa");

    verify(loginView).showProgress();
    verify(loginView).hideProgress();
    verify(loginView).navigateToMainMenu();
}

所以我设置st的值是1,我认为应该没问题。但我明白了:

Wanted but not invoked:
loginView.hideProgress();
-> at     hos.wellhos.com.hosapps.login.LoginPresenterTest.clickBtnLogin(LoginPresenterTest.java:79)

 However, there were other interactions with this mock:
 loginView.setPresenter(
     hos.wellhos.com.hosapps.login.LoginPresenter@4313f5bc
 );
 -> at hos.wellhos.com.hosapps.login.LoginPresenter.<init>    (LoginPresenter.java:43)

任何人都可以帮我解决这个问题,我认为这有一个棘手的问题吗?

1 个答案:

答案 0 :(得分:0)

这可能是一个线程问题。您的Observable订阅了Schedulers.io 即使你然后切换到主线程,所以处理结果这将花费时间。因此,在订阅完成之前,您的验证语句正在处理中。

有几种方法可以解决这个问题:

动态调度程序

而不是将所需的计划程序直接传递到subscribeOn&amp; observeOn方法可以定义为您保存这些变量的成员变量:

Scheduler ioScheduler;
Scheduler mainThreadScheduler;

并在observeOn / subscribeOn声明中使用它们:

.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)

然后,您可以在类构造函数中执行任何其他依赖项时设置它们。对于生产代码,您可以将它们设置为正常Schedulers.io()&amp; AndroidSchedulers.mainThread()但是在您的测试代码中,您可以将它们都设置为Schedulers.immediate()(它只返回当前线程的调度程序)。

<强> RxJavaHooks

在RxJava 1.1.7中引入了一个名为RxJavaHooks的util类,它允许您挂钩到RxJava生命周期的几个部分。其中一个钩子是setOnIOScheduler()方法。这样您就可以更改Scheduler返回的Schedulers.io

在您的情况下,您想将其更改为Schedulers.immediate()

RxJavaHooks.setOnIOScheduler(scheduler -> Schedulers.immediate());

完成测试后,您需要致电:

RxJavaHooks.reset();

这只会使一切恢复正常,这样这种变化不会干扰您在其他地方运行的其他测试。