Sök…


Anmärkningar

Eftersom alla Schedulers-metoder är statiska, kan enhetstester med RxJava-krokar inte köras parallellt på samma JVM-instans. Om de var, skulle en TestScheduler tas bort i mitten av ett enhetstest. Det är i princip nackdelen med att använda Schedulers-klassen.

TestSubscriber

TestSubscribers tillåter dig att undvika arbetet med att skapa din egen prenumerant eller prenumerera Åtgärd <?> För att verifiera att vissa värden var levererade, hur många finns det, om Observera fullbordat, ett undantag togs upp och mycket mer.

Komma igång

Detta exempel visar bara en påstående att värdena 1,2,3 och 4 överfördes till observerbar via onNext.

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

assertValues hävdar att räkningen är korrekt. Om du bara skulle passera några av värdena skulle påståendet misslyckas.

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

assertValues använder metoden equals när man gör påståenden. Detta låter dig enkelt testa klasser som behandlas som data.

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

Detta exempel visar en klass som har en lika definierad och hävdar värdena från det observerbara.

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

Observera också att vi använder den kortare assertValue eftersom vi bara behöver kontrollera för en artikel.

Få alla händelser

Vid behov kan du också be om alla händelser som en lista.

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

Att säga om händelser

Om du vill göra mer omfattande tester på dina evenemang kan du kombinera getOnNextEvents (eller getOn*Events ) med ditt favoritbibliotek:

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

Testning Observable#error

Du kan se till att rätt undantagsklass släpps ut:

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

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

ts.assertError(Exception.class);

Du kan också se till att det exakta undantaget kastades:

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 tillåter dig att kontrollera tid och körning av observerbara istället för att behöva göra upptagna väntningar, gå i trådar eller något för att manipulera systemtiden. Detta är mycket viktigt om du vill skriva enhetstester som är förutsägbara, konsekventa och snabba. Eftersom du manipulerar tiden, finns det inte längre chansen att en tråd har svallit, att ditt test misslyckas på en långsammare maskin eller att du slösar körningstiden upptagen med att vänta på ett resultat.

TestSchedulers kan tillhandahållas via överbelastningen som tar en schemaläggare för alla RxJava-operationer.

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

TestScheduler är ganska grundläggande. Det består bara av tre metoder.

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

Detta låter dig manipulera när TestScheduler ska avfyra alla åtgärder som avser någon tid i framtiden.

När du passerar schemaläggaren fungerar det inte så att TestScheduler ofta används på grund av hur ineffektivt det är. Att skicka schemaläggare till klasser slutar med att ge mycket extra kod för liten vinst. Istället kan du ansluta till RxJava's Schedulers.io () / beräkning () / etc. Detta görs med RxJava's Hooks. Detta låter dig definiera vad som kommer tillbaka från ett samtal från en av Schedulers-metoderna.

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

Denna klass gör det möjligt för användaren att få testschemaläggaren som kommer att anslutas för alla samtal till schemalagare. Ett enhetstest behöver bara för att få denna schemaläggare i sin installation. Det rekommenderas starkt att man begär det i installationen och inte som något vanligt gammalt fält eftersom din TestScheduler kan försöka utlösa åtgärder från ett annat enhetstest när du förskriver tid. Nu blir vårt exempel ovan

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)

Det är så du effektivt kan ta bort systemklockan från ditt enhetstest (åtminstone när det gäller RxJava 😆)



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow