Suche…


Bemerkungen

Da alle Scheduler-Methoden statisch sind, können Komponententests, die die RxJava-Hooks verwenden, nicht parallel in derselben JVM-Instanz ausgeführt werden. Wenn dies der Fall ist, wird ein TestScheduler während eines Komponententests entfernt. Das ist im Grunde der Nachteil der Verwendung der Scheduler-Klasse.

TestSubscriber

Mit TestSubscribers können Sie die Erstellung eines eigenen Abonnenten vermeiden oder Aktion <?> Abonnieren, um zu überprüfen, ob bestimmte Werte geliefert wurden, wie viele vorhanden sind, ob das Observable abgeschlossen wurde, eine Ausnahme ausgelöst wurde und vieles mehr.

Fertig machen

Dieses Beispiel zeigt nur eine Behauptung, dass die Werte 1, 2, 3 und 4 über onNext an das Observable übergeben wurden.

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3,4); // Success

assertValues versichert, dass die Anzahl korrekt ist. Wenn Sie nur einige der Werte übergeben würden, würde die Bestätigung fehlschlagen.

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3); // Fail

assertValues verwendet die equals Methode, wenn assertValues werden. So können Sie auf einfache Weise Klassen testen, die als Daten behandelt werden.

TestSubscriber<Object> ts = TestSubscriber.create();
Observable.just(new Object(), new Object()).subscribe(ts);
ts.assertValues(new Object(), new Object()); // Fail

Dieses Beispiel zeigt eine Klasse, für die eine Gleichheit definiert ist und die Werte aus Observable bestätigt.

public class Room {

    public String floor;
    public String number;

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof Room) {
            Room that = (Room) o;
            return (this.floor.equals(that.floor))
                    && (this.number.equals(that.number));
        }
        return false;
    }
}

TestSubscriber<Room> ts = TestSubscriber.create();
Observable.just(new Room("1", "10")).subscribe(ts);
ts.assertValue(new Room("1", "10"); // Success

Beachten Sie auch, dass wir den kürzeren assertValue da nur ein Element assertValue werden muss.

Alle Ereignisse erhalten

Bei Bedarf können Sie alle Veranstaltungen auch als Liste abfragen.

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
List<Integer> onNextEvents = ts.getOnNextEvents();
List<Throwable> onErrorEvents = ts.getOnErrorEvents();
List<Notification<Integer>> onCompletedEvents = ts.getOnCompletedEvents();

Feststellung von Ereignissen

Wenn Sie umfangreichere Tests für Ihre Ereignisse durchführen möchten, können Sie getOnNextEvents (oder getOn*Events ) mit Ihrer bevorzugten Assertionsbibliothek kombinieren:

Observable<Integer> obs = Observable.just(1,2,3,4)
    .filter( x -> x % 2 == 0);

// note that we instanciate TestSubscriber via the constructor here 
TestSubscriber<Integer> ts = new TestSubscriber();
obs.subscribe(ts);

// Note that we are not using Observable#forEach here
// but java.lang.Iterable#forEach.
// You should never use Observable#forEach unless you know
// exactly what you're doing
ts.getOnNextEvents()
    .forEach( integer -> assertTrue(integer % 2 == 0));

Test Observable#error

Sie können sicherstellen, dass die richtige Ausnahmeklasse ausgegeben wird:

Observable<Integer> obs = Observable.error(new Exception("I am a Teapot"));

TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);

ts.assertError(Exception.class);

Sie können auch sicherstellen, dass die exakte Ausnahme ausgelöst wurde:

Exception e = new Exception("I am a Teapot");
Observable<Integer> obs = Observable.error(e);

TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);

ts.assertError(e);

TestScheduler

TestSchedulers ermöglicht es Ihnen, Zeit und Ausführung von Observablen zu steuern, anstatt busy waits zu tun zu haben, Fäden oder irgendetwas Verbindungssystem Zeit zu manipulieren. Dies ist sehr wichtig, wenn Sie Komponententests schreiben möchten, die vorhersehbar, konsistent und schnell sind. Weil Sie Zeit manipulieren, gibt es nicht mehr die Chance, dass ein Thread wurde ausgehungert, dass Ihr Test auf einem langsameren Maschine ausfällt oder dass Sie die Ausführungszeit beschäftigt Warten auf ein Ergebnis verschwenden.

TestScheduler können über die Überladung bereitgestellt werden, die einen Scheduler für alle RxJava-Vorgänge benötigt.

TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
          .delay(10, TimeUnit.SECONDS, testScheduler)
          .subscribe(subscriber);

try {
    Thread.sleep(TimeUnit.SECONDS.toMillis(11));
} catch (InterruptedException ignored) { }
subscriber.assertValues(1,2,3); // fails

testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success

Der TestScheduler ist ziemlich einfach. Es besteht nur aus drei Methoden.

testScheduler.advanceTimeBy(amount, timeUnit);
testScheduler.advanceTimeTo(when, timeUnit);
testScheduler.triggerActions();

Auf diese Weise können Sie manipulieren, wann der TestScheduler alle Aktionen auslösen soll, die sich auf einige Zeit in der Zukunft beziehen.

Während des Bestehens des Schedulers wird der TestScheduler normalerweise nicht verwendet, da er unwirksam ist. Wenn Sie die Scheduler in Klassen übergeben, erhalten Sie viel zusätzlichen Code für wenig Gewinn. Stattdessen können Sie sich in RxJavas Schedulers.io () / computation () / etc einhaken. Dies geschieht mit RxJavas Hooks. Auf diese Weise können Sie definieren, was von einem Anruf von einer der Scheduler-Methoden zurückgegeben wird.

public final class TestSchedulers {

    public static TestScheduler test() {
        final TestScheduler testScheduler = new TestScheduler();
        RxJavaHooks.reset();
        RxJavaHooks.setOnComputationScheduler((scheduler) -> {
            return testScheduler;
        });
        RxJavaHooks.setOnIOScheduler((scheduler) -> {
            return testScheduler;
        });
        RxJavaHooks.setOnNewThreadScheduler((scheduler) -> {
            return testScheduler;
        });
        return testScheduler;
    }
}

Mit dieser Klasse kann der Benutzer den Test-Scheduler abrufen, der für alle Aufrufe an Scheduler angeschlossen wird. Ein Komponententest müsste diesen Scheduler einfach in sein Setup bringen. Es wird dringend empfohlen es im Setup aquiring und nicht als ein gutes altes Feld, weil Ihr TestScheduler zu triggerActions von einer anderen Gerät zu testen versuchen können, wenn Sie vorher Zeit. Nun wird unser Beispiel oben

TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
          .delay(10, TimeUnit.SECONDS, testScheduler)
          .subscribe(subscriber);
testScheduler.advanceTimeBy(9, TimeUnit.SECONDS);
subscriber.assertValues(); // success (delay hasn't finished)
testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success (delay has finished)

So können Sie die Systemuhr effektiv aus Ihrem Unit-Test entfernen (zumindest was RxJava betrifft)



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow