但是,与此模拟还有其他交互:
However, there were other interactions with this mock:
所以我有问题,这是我的演示者代码:
@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)
谁能帮我解决这个问题,我觉得这有什么棘手的问题?
这可能是线程问题。您的 Observable
正在 Schedulers.io
上订阅
即使您随后切换到主线程来处理结果,这也需要时间。因此,在订阅完成之前正在处理您的验证声明。
有几种方法可以解决这个问题:
动态调度程序
无需将所需的调度程序直接传递给您的 subscribeOn
和 observeOn
方法,您可以定义为您保存这些的成员变量:
Scheduler ioScheduler;
Scheduler mainThreadScheduler;
并在 observeOn
/subscribeOn
语句中使用它们:
.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)
然后您可以像在 class 构造函数中设置任何其他依赖项一样设置它们。对于生产代码,您可以将它们设置为正常的 Schedulers.io()
& AndroidSchedulers.mainThread()
但是在您的测试代码中,您可以将它们都设置为 Schedulers.immediate()
(这只是 returns 当前的调度程序线程)。
RxJavaHooks
在 RxJava 1.1.7 中引入了一个名为 RxJavaHooks
的实用程序 class,它允许您挂接到 RxJava 生命周期的多个部分。这些钩子之一是 setOnIOScheduler()
方法。这允许您更改 Schedulers.io
.
返回的 Scheduler
在您的情况下,您想将其更改为 Schedulers.immediate()
:
RxJavaHooks.setOnIOScheduler(scheduler -> Schedulers.immediate());
完成测试后,您需要致电:
RxJavaHooks.reset();
这只会让一切恢复正常,这样这一变化就不会干扰您在其他地方 运行 进行的其他测试。
所以我有问题,这是我的演示者代码:
@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)
谁能帮我解决这个问题,我觉得这有什么棘手的问题?
这可能是线程问题。您的 Observable
正在 Schedulers.io
上订阅
即使您随后切换到主线程来处理结果,这也需要时间。因此,在订阅完成之前正在处理您的验证声明。
有几种方法可以解决这个问题:
动态调度程序
无需将所需的调度程序直接传递给您的 subscribeOn
和 observeOn
方法,您可以定义为您保存这些的成员变量:
Scheduler ioScheduler;
Scheduler mainThreadScheduler;
并在 observeOn
/subscribeOn
语句中使用它们:
.subscribeOn(ioScheduler)
.observeOn(mainThreadScheduler)
然后您可以像在 class 构造函数中设置任何其他依赖项一样设置它们。对于生产代码,您可以将它们设置为正常的 Schedulers.io()
& AndroidSchedulers.mainThread()
但是在您的测试代码中,您可以将它们都设置为 Schedulers.immediate()
(这只是 returns 当前的调度程序线程)。
RxJavaHooks
在 RxJava 1.1.7 中引入了一个名为 RxJavaHooks
的实用程序 class,它允许您挂接到 RxJava 生命周期的多个部分。这些钩子之一是 setOnIOScheduler()
方法。这允许您更改 Schedulers.io
.
Scheduler
在您的情况下,您想将其更改为 Schedulers.immediate()
:
RxJavaHooks.setOnIOScheduler(scheduler -> Schedulers.immediate());
完成测试后,您需要致电:
RxJavaHooks.reset();
这只会让一切恢复正常,这样这一变化就不会干扰您在其他地方 运行 进行的其他测试。