Testowanie RxJS z użyciem Marbles

Jakub Szafraniec

Jakub Szafraniec

Senior JavaScript Developer

Agenda

  • W czym jest problem?
  • Teoria
  • Praktyka

W czym jest problem?

let result;

service.getSomething$().subscribe((value) => {
    result = value;
});
it('should ....',           () => {
tick(100);
expect(result).toEqual(A);
tick(300);
expect(result).toEqual(B);
tick(500);
expect(result).toEqual(C);
350?

START ->   100ms    A    300ms    B    500ms    C   -> END

fakeAsync(

Wady fakeAsync

  • Brak precyzyjnej kontroli czasu
  • Brak kontroli początku/zakończenia subskrypcji
  • Skomplikowane testowanie obsługi błędów
  • Dużo boilerplate

RxJS Marbles

it('generate the stream correctly', () => {
  testScheduler.run(helpers => {
  












  }); 
});
const e1 = cold(' -a--b--c---|');
const subs = '    ^----------!';
const expected = '-a-----c---|';
const { cold, 
        expectObservable, 
        expectSubscriptions } = helpers;
expectSubscriptions(e1.subscriptions)
        .toBe(subs);
expectObservable(e1.pipe(/without b/))
        .toBe(expected);
import {TestScheduler} from 'rxjs/testing';
 
const testScheduler = 
    new TestScheduler((actual, expected) 
    => {
        expect(actual).toEqual(expected);
});
cold('--a--b--c', {
   a: 'foo',
   b: 123,
   c: {
      x: {
         y: 3;
      },
      z: false
   }
})
  • cold()
  • hot()
  • expectObservable()
  • expectSubscriptions()
  • flush()

RunHelpers

Składnia języka Marbles

  • '  ' spacja - ignorowana
  • '-' jednostka ramki czasu
  • '20ms', '1s', '1m' - czas pomiędzy eventami
  • '|' koniec strumienia
  • '#' błąd
  • 'a' 'b' '1' '2' symbole eventów w strumieniu
  • '()' grupowanie eventów w jednej jednostce czasu
  • '^' początek subskrypcji
  • '!' koniec subskrypcji
cold('            a---b 100ms (ab) 100ms c---#')
expect(/c/).toBe('----- 100ms -    100ms c---#')

Przykłady użycia w praktyce

@szafraniec_kuba

https://rxjs.dev/guide/testing/marble-testing

https://github.com/kszafraniec/rxjs-marbles-demo

Made with Slides.com