@Override public void onBarcodeReceived(final String barcode) {
view.showProgress();
if (!textUtil.isEmpty(barcode)) {
subscriptions.add(
interactor.getSearchResultByBarcode(barcode).subscribe(subscriberForSearchResults(true)));
}
}
private Subscriber<PriceAndStockActivityViewModel> subscriberForSearchResults(
boolean fromBarcode) {
return new BaseSubscriber<PriceAndStockActivityViewModel>() {
@Override public void onNext(PriceAndStockActivityViewModel priceAndStockActivityViewModel) {
super.onNext(priceAndStockActivityViewModel);
view.updateView(priceAndStockActivityViewModel);
}
@Override public void onError(Throwable e) {
super.onError(e);
view.hideProgress();
view.organizeScreenComponentsByVisibility(true);
view.onError(e);
}
};
}
我想测试名为onBarcodeReceived的方法,如下所示
@Test public void should_updateViewByViewModel_when_AnyBarcodeReceived() {
String barcode = "123123123";
PriceAndStockActivityViewModel viewModel = getPriceAndStockActivityViewModel(barcode);
when(textUtil.isEmpty(barcode)).thenReturn(false);
when(interactor.getSearchResultByBarcode(anyString())).thenReturn(Observable.just(viewModel));
presenter.onBarcodeReceived(barcode);
verify(view).showProgress();
verify(interactor).getSearchResultByBarcode(anyString());
verify(view).updateView(any(PriceAndStockActivityViewModel.class));
}
由于onNext在不同的线程中运行,因此通常不会到达view.updateView。它看起来很简单,但我找不到如何解决它。有没有办法验证updateView?
答案 0 :(得分:1)
我认为getSearchResultByBarcode()
适用于后台线程。所以我想知道你如何能够从这个后台线程更改你的UI?
我将subscriber
的执行更改为Android的主线程,以便您可以安全地操纵视图,无论将来getSearchResultByBarcode()
的线程是否发生变化。但是不会直接对Scheduler
进行硬编码,而是将其注入到演示者类中,例如通过构造函数。当然,当你创建“真正的”演示者时,你会传递AndroidSchedulers.mainThread()
:
public MyPresenter(, Scheduler observeScheduler) {
...
this.observeScheduler = observeScheduler;
}
....
@Override
public void onBarcodeReceived(final String barcode) {
view.showProgress();
if (!textUtil.isEmpty(barcode)) {
subscriptions.add(interactor.getSearchResultByBarcode(barcode)
.observeOn(observeScheduler)
.subscribe(subscriberForSearchResults(true)));
}
}
然后在您的测试中,在构建Presenter
时,您将使用Schedulers.immediate()
(如果您正在使用RxJava 1.x或Schedulers.trampoline()
,如果您正在使用RxJava 2.x那个应该可以在没有使用Mockito的单元测试中使用任何timeout()
的情况下工作......毕竟你希望它们尽可能快地运行。
和一个无关的事情 - 您可以使用org.apache.commons.lang3.StringUtils
替换android.text.TextUtils
- 它具有大致相同的功能,但您不需要在单元测试中模拟它。
答案 1 :(得分:0)
为了等待另一个线程完成,您可以使用此Mockito功能:verify with timeout。
verify(view, timeout(100)).updateView(any(PriceAndStockActivityViewModel.class));
或者使用某些线程同步方法,如CountDownLatch。请参阅Mockito here的示例。