如何对Flowable.interval进行单元测试?

huangapple go评论73阅读模式
英文:

How to unit test Flowable.interval?

问题

以下是翻译好的部分:

"Here is the error that I get:"(这是我得到的错误消息:)

"Wanted but not invoked:"(期望但未调用:)

"However, there were other interactions with this mock:"(但是,模拟对象还有其他交互:)

"How I can solve this?"(我如何解决这个问题?)

希望这能帮助您解决问题。如果您需要更多信息,请随时提出。

英文:

I have the following code inside the presenter.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

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 -&gt; view.onRegistrationSuccessful(), view::handleError);

    disposables.add(disposable);
  }

  @Override public void dispose() {
    RxUtil.dispose(disposables);
  }

  public interface View extends Presenter.View {

    void onRegistrationSuccessful();

    void displaySuccessMessage();
  }
}

<!-- end snippet -->

Now, I want to write unit test for that method.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

@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 -&gt; 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();
  }
}

<!-- end snippet -->

Here is the error that I get:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

Wanted but not invoked:
view.onRegistrationSuccessful();
-&gt; at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)

However, there were other interactions with this mock:
view.displaySuccessMessage();
-&gt; at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)


Wanted but not invoked:
view.onRegistrationSuccessful();
-&gt; at com.test.presentation.signup.SignUpPresenterTest.shouldDisplaySuccessMessage(SignUpPresenterTest.java:36)

However, there were other interactions with this mock:
view.displaySuccessMessage();
-&gt; at com.test.presentation.signup.SignUpPresenter.redirectToLogInScreenAfterOneSecond(SignUpPresenter.java:28)

<!-- end snippet -->
How I can solve this?

答案1

得分: 2

以下是翻译好的部分:

@Test public void shouldDisplaySuccessMessage() {
    presenter.redirectToLogInScreenAfterOneSecond();
    testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);

    Mockito.verify(view).displaySuccessMessage();
    Mockito.verify(view).onRegistrationSuccessful();
}

Also you don't need that many operators after interval but use the mainThread scheduler directly:

Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
    .subscribe(aLong -> view.onRegistrationSuccessful(), view::handleError);

and replace the mainThread scheduler:

@Before public void setUp() {
    testScheduler = new TestScheduler();
    RxAndroidPlugins.setMainThreadSchedulerHandler(scheduler -> testScheduler);
    presenter = new SignUpPresenter();
    presenter.setView(view);
}

希望这能帮助你。如果有其他问题,请随时提出。

英文:

You have to move the time after the flow setup:

@Test public void shouldDisplaySuccessMessage() {
    presenter.redirectToLogInScreenAfterOneSecond();
    testScheduler.advanceTimeTo(1, TimeUnit.SECONDS);

    Mockito.verify(view).displaySuccessMessage();
    Mockito.verify(view).onRegistrationSuccessful();
}

Also you don't need that many operators after interval but use the mainThread scheduler directly:

Disposable disposable = Flowable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
    .subscribe(aLong -&gt; view.onRegistrationSuccessful(), view::handleError);

and replace the mainThread scheduler:

@Before public void setUp() {
    testScheduler = new TestScheduler();
    RxAndroidPlugins.setMainThreadSchedulerHandler(scheduler -&gt; testScheduler);
    presenter = new SignUpPresenter();
    presenter.setView(view);
}

huangapple
  • 本文由 发表于 2020年1月6日 16:19:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/59608753.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定