如何进行单元测试Flowable.interval?
How to unit test Flowable.interval?
我在演示程序中有以下代码。
public class SignUpPresenter implements Presenter {
private CompositeDisposable disposables;
private View view;
@Inject public SignUpPresenter() {
}
public void setView(View view) {
this.view = view;
}
public void redirectToLogInScreenAfterOneSecond() {
disposables = RxUtil.initDisposables(disposables);
view.displaySuccessMessage();
Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> view.onRegistrationSuccessful(), view::handleError);
disposables.add(disposable);
}
@Override public void dispose() {
RxUtil.dispose(disposables);
}
public interface View extends Presenter.View {
void onRegistrationSuccessful();
void displaySuccessMessage();
}
}
现在,我想为该方法编写单元测试。
@RunWith(PowerMockRunner.class)
public class SignUpPresenterTest {
@Rule TrampolineSchedulerRule trampolineSchedulerRule = new TrampolineSchedulerRule();
@Mock SignUpPresenter.View view;
private SignUpPresenter presenter;
private TestScheduler testScheduler;
@Before public void setUp() {
testScheduler = new TestScheduler();
RxJavaPlugins.setComputationSchedulerHandler(scheduler -> testScheduler);
presenter = new SignUpPresenter();
presenter.setView(view);
}
@Test public void shouldDisplaySuccessMessage() {
testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);
presenter.redirectToLogInScreenAfterOneSecond();
Mockito.verify(view).displaySuccessMessage();
Mockito.verify(view).onRegistrationSuccessful();
}
}
这是我得到的错误:
Wanted but not invoked:
view.onRegistrationSuccessful();
-> at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)
However, there were other interactions with this mock:
view.displaySuccessMessage();
-> at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)
Wanted but not invoked:
view.onRegistrationSuccessful();
-> at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)
However, there were other interactions with this mock:
view.displaySuccessMessage();
-> at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)
我该如何解决这个问题?
你必须在流程设置后移动时间:
@Test public void shouldDisplaySuccessMessage() {
presenter.redirectToLogInScreenAfterOneSecond();
testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);
Mockito.verify(view).displaySuccessMessage();
Mockito.verify(view).onRegistrationSuccessful();
}
另外,在 interval 之后你不需要那么多操作符,而是直接使用 mainThread 调度器:
Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.subscribe(aLong -> view.onRegistrationSuccessful(), view::handleError);
并替换主线程调度程序:
@Before public void setUp() {
testScheduler = new TestScheduler();
RxAndroidPlugins.setMainThreadSchedulerHandler(scheduler -> testScheduler);
presenter = new SignUpPresenter();
presenter.setView(view);
}
我在演示程序中有以下代码。
public class SignUpPresenter implements Presenter {
private CompositeDisposable disposables;
private View view;
@Inject public SignUpPresenter() {
}
public void setView(View view) {
this.view = view;
}
public void redirectToLogInScreenAfterOneSecond() {
disposables = RxUtil.initDisposables(disposables);
view.displaySuccessMessage();
Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> view.onRegistrationSuccessful(), view::handleError);
disposables.add(disposable);
}
@Override public void dispose() {
RxUtil.dispose(disposables);
}
public interface View extends Presenter.View {
void onRegistrationSuccessful();
void displaySuccessMessage();
}
}
现在,我想为该方法编写单元测试。
@RunWith(PowerMockRunner.class)
public class SignUpPresenterTest {
@Rule TrampolineSchedulerRule trampolineSchedulerRule = new TrampolineSchedulerRule();
@Mock SignUpPresenter.View view;
private SignUpPresenter presenter;
private TestScheduler testScheduler;
@Before public void setUp() {
testScheduler = new TestScheduler();
RxJavaPlugins.setComputationSchedulerHandler(scheduler -> testScheduler);
presenter = new SignUpPresenter();
presenter.setView(view);
}
@Test public void shouldDisplaySuccessMessage() {
testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);
presenter.redirectToLogInScreenAfterOneSecond();
Mockito.verify(view).displaySuccessMessage();
Mockito.verify(view).onRegistrationSuccessful();
}
}
这是我得到的错误:
Wanted but not invoked:
view.onRegistrationSuccessful();
-> at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)
However, there were other interactions with this mock:
view.displaySuccessMessage();
-> at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)
Wanted but not invoked:
view.onRegistrationSuccessful();
-> at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)
However, there were other interactions with this mock:
view.displaySuccessMessage();
-> at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)
你必须在流程设置后移动时间:
@Test public void shouldDisplaySuccessMessage() {
presenter.redirectToLogInScreenAfterOneSecond();
testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);
Mockito.verify(view).displaySuccessMessage();
Mockito.verify(view).onRegistrationSuccessful();
}
另外,在 interval 之后你不需要那么多操作符,而是直接使用 mainThread 调度器:
Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.subscribe(aLong -> view.onRegistrationSuccessful(), view::handleError);
并替换主线程调度程序:
@Before public void setUp() {
testScheduler = new TestScheduler();
RxAndroidPlugins.setMainThreadSchedulerHandler(scheduler -> testScheduler);
presenter = new SignUpPresenter();
presenter.setView(view);
}