2017-01-18 2 views
0
@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); 
     } 
    }; 
    } 

Ich wollte schreiben Methode testen genannt onBarcodeReceived wie unterWie Unit-Test für RxJava CompositeSubscription

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

Da OnNext in einem anderen Thread läuft seinen normalen nicht view.updateView zu erreichen. Es sieht einfach aus, aber ich konnte es nicht lösen. Gibt es eine Möglichkeit, updateView zu verifizieren?

+1

Ich stimme für das Schließen dieser Frage als Off-Thema, weil eigentlich meine Implementierung korrekt war, aber es gab andere Fehler wegen mir. keine Beziehung mit dem Code. Leute können verwirren, die Frage rot zu haben. Bitte lösche es. –

Antwort

0

Um auf den Abschluss eines anderen Threads zu warten, können Sie diese Mockito-Funktion verwenden: verify with timeout.

verify(view, timeout(100)).updateView(any(PriceAndStockActivityViewModel.class)); 

Oder einige Mittel zur Thread-Synchronisierung wie CountDownLatch verwenden. Siehe Beispiel für Mockito here.

+0

es ist nicht nur etwas über Threading-Problem. Ich glaube, dass es ein Problem mit rxjava geben muss ... –

+0

@ MustafaGüven Haben Sie versucht, Timeout hinzuzufügen? Ich sehe hier gar nichts RxJava. –

+0

ja ich habe hinzugefügt, aber hat nicht funktioniert. –

1

Ich nehme an getSearchResultByBarcode() arbeitet auf einem Hintergrundthread. Ich frage mich also, wie Sie Ihre Benutzeroberfläche von diesem Hintergrund Thread ändern können?

Ich würde die Ausführung Ihrer subscriber Android Haupt Thread ändern, so dass Sie die Ansicht sicher manipulieren können, unabhängig davon, ob der Thread getSearchResultByBarcode() in der Zukunft ändert. Allerdings wird das Scheduler nicht direkt codiert, sondern lässt es sich zB über den Konstruktor in die Presenter-Klasse einspeisen. Natürlich, wenn Sie den „echten“ Moderator erstellen, die Sie in AndroidSchedulers.mainThread() passieren würden:

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))); 
    } 
} 

Dann in Ihrem Test, wenn die Presenter konstruieren würden Sie Schedulers.immediate() verwenden (wenn Sie 1 verwenden sind RxJava. x oder Schedulers.trampoline() wenn Sie RxJava 2.x Version verwenden. Das ohne Verwendung von timeout() s in Ihren Unit-Tests mit Mockito funktionieren soll ... doch Sie wollen so schnell wie möglich auszuführen.

und eine unabhängige Ding - Sie können org.apache.commons.lang3.StringUtils als Ersatz von android.text.TextUtils verwenden - es hat ungefähr die gleiche Funktionalität, aber Sie müssen es in Ihrer Einheit nicht verspotten Tests.