Zoeken…


Opmerkingen

Omdat alle Schedulers-methoden statisch zijn, kunnen unit-tests met de RxJava-hooks niet parallel op hetzelfde JVM-exemplaar worden uitgevoerd. Als ze waar waren, zou een TestScheduler worden verwijderd tijdens een unit-test. Dat is eigenlijk het nadeel van het gebruik van de klasse Planners.

TestSubscriber

Met TestSubscribers kunt u vermijden dat u uw eigen abonnee maakt of actie <?> Abonneren om te controleren of bepaalde waarden zijn geleverd, hoeveel er zijn, als de Observable is voltooid, een uitzondering is opgeworpen en nog veel meer.

Ermee beginnen

Dit voorbeeld toont alleen een bewering dat de waarden 1,2,3 en 4 zijn ingevoerd in de Waarneembare via onNext.

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

assertValues beweert dat de telling correct is. Als u slechts enkele waarden zou doorgeven, zou de bewering mislukken.

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

assertValues gebruikt de methode equals bij het doen van assertValues . Hiermee kunt u gemakkelijk klassen testen die als gegevens worden behandeld.

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

Dit voorbeeld toont een klasse met een gedefinieerde gelijkheid die de waarden uit Observable bevestigt.

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

assertValue ook rekening mee dat we de kortere assertValue omdat we slechts op één item hoeven te controleren.

Alle evenementen ophalen

Indien nodig kunt u ook vragen om alle evenementen als een lijst.

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

Beweren over evenementen

Als je uitgebreidere tests op je evenementen wilt doen, kun je getOnNextEvents (of getOn*Events ) combineren met je favoriete beweringenbibliotheek:

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

Testen Observable#error

U kunt ervoor zorgen dat de juiste uitzonderingsklasse wordt uitgezonden:

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

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

ts.assertError(Exception.class);

U kunt er ook voor zorgen dat de exacte uitzondering is gegenereerd:

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

Met TestSchedulers kunt u de tijd en uitvoering van Observables besturen in plaats van druk te moeten wachten, lid worden van threads of iets om de systeemtijd te manipuleren. Dit is ZEER belangrijk als u eenheidstests wilt schrijven die voorspelbaar, consistent en snel zijn. Omdat u tijd manipuleert, is er niet langer de kans dat een thread uitgehongerd raakt, dat uw test mislukt op een langzamere machine of dat u uitvoeringstijd verspilt aan het wachten op een resultaat.

TestSchedulers kunnen worden geleverd via de overbelasting waarvoor een planner nodig is voor alle RxJava-bewerkingen.

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

De TestScheduler is vrij eenvoudig. Het bestaat slechts uit drie methoden.

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

Hiermee kunt u manipuleren wanneer de TestScheduler alle acties in de toekomst moet activeren.

Hoewel het passeren van de planner werkt, is dit niet hoe de TestScheduler vaak wordt gebruikt vanwege de ineffectiviteit ervan. Het doorgeven van planners in klassen levert uiteindelijk veel extra code op voor weinig winst. In plaats daarvan kunt u aansluiten op Schedulers.io () / computation () / etc van RxJava. Dit wordt gedaan met RxJava's Hooks. Hiermee kunt u definiëren wat er wordt geretourneerd door een oproep van een van de methoden van Planners.

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

Met deze klasse kan de gebruiker de testplanner ophalen die wordt aangesloten voor alle oproepen naar planners. Een eenheidstest zou deze planner gewoon in zijn setup moeten krijgen. Het wordt ten zeerste aanbevolen om het in de setup te krijgen en niet als een gewoon oud veld, omdat uw TestScheduler mogelijk probeert acties in te schakelen vanuit een andere eenheidstest wanneer u de tijd vooruitgaat. Nu wordt ons voorbeeld hierboven

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)

Dat is hoe je de systeemklok effectief uit je unit-test kunt verwijderen (tenminste wat RxJava betreft 😆)



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow