Skip to content

Test con TestScheduler ​

Il TestScheduler di RxJS è uno strumento potente per testare accuratamente gli operatori basati sul tempo. Questo capitolo spiega sistematicamente come testare utilizzando TestScheduler.

Cos'è TestScheduler? ​

Normalmente, gli Observable funzionano in base al tempo. Ad esempio, delay() e debounceTime() sono operatori che attendono un certo tempo. Nei test, attendere effettivamente è inefficiente, quindi TestScheduler è un meccanismo che permette di testare immediatamente usando il tempo virtuale.

TIP

Con TestScheduler si usa il "tempo virtuale", quindi non è necessario attendere il tempo reale.

Struttura Base di TestScheduler ​

ts
import { TestScheduler } from 'rxjs/testing';
import { describe, it, beforeEach, expect } from 'vitest';

describe('Basi di TestScheduler', () => {
  let testScheduler: TestScheduler;

  beforeEach(() => {
    testScheduler = new TestScheduler((actual, expected) => {
      expect(actual).toEqual(expected);
    });
  });

  it('test semplice', () => {
    testScheduler.run(({ cold, expectObservable }) => {
      const source$ = cold('--a--b--c|');
      const expected =  '--a--b--c|';

      expectObservable(source$).toBe(expected);
    });
  });
});
  • cold(): Crea un Cold Observable che inizia lo stream in modo indipendente per ogni sottoscrizione
  • hot(): Crea un Hot Observable con uno stream già in corso
  • expectObservable(): Verifica l'output dell'Observable con la notazione marble

Cold Observable e Hot Observable ​

TipoCaratteristicaUtilizzo
Cold ObservableFa fluire i dati dall'inizio ogni volta che viene sottoscrittoRichieste HTTP, ecc.
Hot ObservableIl flusso di dati è già iniziato e viene condiviso con i sottoscrittoriEventi utente, WebSocket, ecc.

Basi della Notazione Marble ​

La notazione marble è una tecnica per rappresentare il passare del tempo di un Observable con stringhe.

SimboloSignificato
-Passare del tempo (1 frame)
a, b, cValori emessi
``
#Errore
() Emissione simultanea di più valori (eventi multipli)

Esempio ​

--a--b--c|    // Dopo 2 frame a, poi b, c, completamento

Esempi di Test con Tempo Virtuale ​

Test di debounceTime ​

ts
import { describe, it, expect, beforeEach } from 'vitest';
import { debounceTime, map } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';

describe('Test usando tempo virtuale', () => {
  let testScheduler: TestScheduler;

  beforeEach(() => {
    testScheduler = new TestScheduler((actual, expected) => {
      expect(actual).toEqual(expected);
    });
  });

  it('test dell\'operatore debounceTime', () => {
    testScheduler.run(({ cold, expectObservable }) => {
      const source$ = cold('--a--b----c|');
      const result$ = source$.pipe(
        debounceTime(20),
        map(x => x.toUpperCase())
      );
      const expected =    '-----------(C|)';  // ←Questo!

      expectObservable(result$).toBe(expected, { B: 'B', C: 'C' });
    });
  });
});

Test di Gestione degli Errori ​

ts
import { describe, it, expect, beforeEach } from 'vitest';
import { catchError} from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { of } from 'rxjs';

describe('Test di gestione degli errori', () => {
  let testScheduler: TestScheduler;

  beforeEach(() => {
    testScheduler = new TestScheduler((actual, expected) => {
      expect(actual).toEqual(expected);
    });
  });

  it('cattura errore con catchError', () => {
    testScheduler.run(({ cold, expectObservable }) => {
      const source$ = cold('--a--#');
      const result$ = source$.pipe(
        catchError(() => of('X'))
      );

      const expected =    '--a--(X|)';

      expectObservable(result$).toBe(expected);
    });
  });
});
  • Con TestScheduler è possibile testare senza attendere il tempo reale
  • Comprendere e utilizzare correttamente la differenza tra Observable Cold/Hot
  • Utilizzare la notazione marble per visualizzare il passare del tempo
  • È possibile testare con precisione anche stream asincroni complessi

[!NEXT] Successivamente, impareremo tecniche più avanzate di marble testing (personalizzazione delle stringhe marble e combinazione di più stream).

Pubblicato sotto licenza CC-BY-4.0.