Recherche…


Remarques

Toutes les méthodes de Schedulers étant statiques, les tests unitaires utilisant les hooks RxJava ne peuvent pas être exécutés en parallèle sur la même instance de JVM. Si c'est le cas, un seul TestScheduler serait supprimé au milieu d'un test unitaire. C'est fondamentalement l'inconvénient d'utiliser la classe Schedulers.

TestSubscriber

TestSubscribers vous permet d'éviter le travail de création de votre propre abonné ou de vous inscrire Action <?> Pour vérifier que certaines valeurs ont été livrées, combien il y en a, si l'observable est terminé, une exception a été soulevée et beaucoup plus.

Commencer

Cet exemple montre simplement que les valeurs 1, 2, 3 et 4 sont passées dans l’observable via onNext.

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

assertValues affirme que le compte est correct. Si vous ne deviez transmettre que certaines des valeurs, l'assertion échouerait.

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

assertValues utilise la méthode equals lors des assertValues . Cela vous permet de tester facilement les classes traitées comme des données.

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

Cet exemple montre une classe qui a un égal défini et qui affirme les valeurs de l'observable.

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

Notez également que nous utilisons la valeur assertValue la plus assertValue car nous n'avons besoin que de vérifier un élément.

Obtenir tous les événements

Si nécessaire, vous pouvez également demander tous les événements sous forme de liste.

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

Affirmer sur des événements

Si vous souhaitez effectuer des tests plus approfondis sur vos événements, vous pouvez combiner getOnNextEvents (ou getOn*Events ) avec votre bibliothèque d'assertions préférée:

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 de l' Observable#error

Vous pouvez vous assurer que la classe d'exception correcte est émise:

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

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

ts.assertError(Exception.class);

Vous pouvez également vous assurer que l’exception exacte a été lancée:

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 vous permet de contrôler le temps et l'exécution des observables au lieu d'avoir à faire des attentes occupées, à joindre des threads ou à manipuler l'heure du système. Ceci est très important si vous voulez écrire des tests unitaires prévisibles, cohérents et rapides. Parce que vous manipulez le temps, il n'y a plus de chance qu'un thread soit affamé, que votre test échoue sur une machine plus lente ou que vous perdiez du temps à attendre un résultat.

TestSchedulers peut être fourni via la surcharge qui prend un planificateur pour toutes les opérations 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

Le TestScheduler est assez basique. Il ne comprend que trois méthodes.

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

Cela vous permet de manipuler lorsque le TestScheduler doit déclencher toutes les actions concernant un certain temps dans le futur.

En passant le planificateur fonctionne, ce n'est pas la façon dont le TestScheduler est couramment utilisé en raison de son inefficacité. Passer des ordonnanceurs en classes finit par fournir beaucoup de code supplémentaire pour un gain minime. Au lieu de cela, vous pouvez accéder à Schedulers.io () / computation () / etc de RxJava. Ceci est fait avec les crochets de RxJava. Cela vous permet de définir ce qui est renvoyé par un appel provenant d’une des méthodes Schedulers.

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

Cette classe permet à l'utilisateur d'obtenir le planificateur de test qui sera connecté à tous les appels aux planificateurs. Un test unitaire devrait simplement avoir ce planificateur dans sa configuration. Il est fortement recommandé de l’acquérir dans le programme d’installation et de ne pas utiliser de vieux champ, car votre TestScheduler peut essayer de déclencher des actions à partir d’un autre test unitaire lorsque vous avancez. Maintenant, notre exemple ci-dessus devient

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)

C'est ainsi que vous pouvez supprimer efficacement l'horloge système de votre test unitaire (au moins pour ce qui concerne RxJava 😆)



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow