Ricerca…


Osservazioni

Poiché tutti i metodi Schedulers sono statici, i test delle unità che utilizzano gli hook RxJava non possono essere eseguiti in parallelo sulla stessa istanza JVM. Se loro dove, un TestScheduler verrebbe rimosso nel bel mezzo di un test unitario. Questo è fondamentalmente il lato negativo dell'uso della classe Schedulers.

TestSubscriber

TestSubscribers ti consente di evitare che il lavoro crei il tuo Subscriber o abbonati all'azione <?> Per verificare che alcuni valori siano consegnati, quanti ne siano, se l'Observable sia completato, sia stata sollevata un'eccezione e molto altro ancora.

Iniziare

Questo esempio mostra solo un'asserzione secondo cui i valori 1,2,3 e 4 sono passati all'Osservable tramite onNext.

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

assertValues afferma che il conteggio è corretto. Se dovessi passare solo alcuni dei valori, l'asserzione fallirebbe.

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

assertValues usa il metodo equals quando fa affermazioni. Ciò consente di testare facilmente classi considerate come dati.

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

Questo esempio mostra una classe che ha un uguaglianza definita e che asserisce i valori dall'osservabile.

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

Inoltre, prendi nota che utilizziamo il valore assertValue più assertValue perché dobbiamo solo controllare un articolo.

Ottenere tutti gli eventi

Se necessario, puoi anche chiedere tutti gli eventi come una 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();

Affermando sugli eventi

Se vuoi fare test più estesi sui tuoi eventi, puoi combinare getOnNextEvents (o getOn*Events ) con la tua libreria di asserzione preferita:

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 di Observable#error

Puoi assicurarti che venga emessa la classe di eccezione corretta:

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

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

ts.assertError(Exception.class);

Puoi anche assicurarti che sia stata lanciata l'eccezione esatta:

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 ti permette di controllare il tempo e l'esecuzione degli Osservabili invece di dover fare attese occupate, unire discussioni o qualsiasi cosa per manipolare il tempo del sistema. Questo è MOLTO importante se si desidera scrivere test unitari prevedibili, coerenti e veloci. Poiché stai manipolando il tempo, non c'è più la possibilità che un thread sia affamato, che il tuo test fallisca su una macchina più lenta o che rifiuti tempo di esecuzione occupato ad aspettare un risultato.

TestSchedulers può essere fornito tramite il sovraccarico che richiede un Utilità di pianificazione per tutte le operazioni RxJava.

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

Il TestScheduler è piuttosto semplice. Consiste solo di tre metodi.

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

Questo ti consente di manipolare quando il TestScheduler deve attivare tutte le azioni relative a un certo periodo di tempo in futuro.

Mentre passa lo schedulatore funziona, questo non è il modo in cui il TestScheduler viene comunemente usato a causa di quanto sia inefficace. Passare scheduler in classi finisce per fornire un sacco di codice extra per poco guadagno. Invece, puoi collegarti a Schedulers.io () / computation () / etc di RxJava. Questo è fatto con RxJava's Hooks. Ciò consente di definire cosa viene restituito da una chiamata da uno dei metodi Pianificatori.

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

Questa classe consente all'utente di ottenere lo scheduler di test che verrà collegato per tutte le chiamate agli Scheduler. Un test unitario avrebbe solo bisogno di ottenere questo programmatore nella sua configurazione. Si consiglia vivamente di acquisirlo nel setup e non come un semplice campo vecchio perché il TestScheduler potrebbe tentare di attivare le azioni da un altro test unitario quando si avanza in anticipo. Ora il nostro esempio sopra diventa

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)

È così che puoi rimuovere efficacemente l'orologio di sistema dal test dell'unità (almeno per quanto riguarda RxJava) 😆)



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow