RxJS 測試非同步運算子,如 delay()

我該如何訂閱後去得知 type 是不是 decrement

// decrementAsync.js
import { of } from 'rxjs';
import { delay, filter } from 'rxjs/operators';

export const decrementAsync = ({ dispatch }) => {
  of(null)
    .pipe(delay(1000))
    .subscribe(() => dispatch('decrement'));
};
// decrementAsync.spec.js
import { marbles } from 'rxjs-marbles/jest';

import { decrementAsync } from './decrementAsync';

describe('decrementAsync', () => {
  it('should handle decrementAsync', marbles((m) => {
    const dispatch = (type) => {
      const source =  m.hot('--^-a-----|', { a: null });
      const subs =            '^-------!';
      const expected =        '---a----|';

      const destination = source.pipe(delay(m.time('-|')));

      m.expect(destination).toBeObservable(expected);
      m.expect(source).toHaveSubscriptions(subs);

      m.expect(type).toBe('decrement');
    };

    decrementAsync({ dispatch });
  }));
});

你有看過官方的測試文件嗎?

https://angular.io/guide/testing#marble-error-testing

可以利用 spyOn 的方式來測試,以下有 cheetsheet
http://tobyho.com/2011/12/15/jasmine-spy-cheatsheet/

因為有 delay 屬於非同步的測試
可以參考這篇

好吧,我遇到你所說的問題了

測試程式碼大概會長這樣

import { TestScheduler } from 'rxjs/testing';
...

it('should clear out meesages array after 3 sec', () => {
    const testScheduler = new TestScheduler((actual, expected) => {
      expect(component.messages.length).toBe(0);
    });

    testScheduler.run(({ cold, expectObservable }) => {
      const input = cold('-a--|');
      const output = input.pipe(tap(v => component.message$.next({} as any)));
      const expected = '-- 2999ms a ---|';
      expectObservable(component.remover$).toBe(expected);
    });
  });

要被測試的程式碼

  message$ = this.service.message$;
  messages: CommandModel[] = [];
  tasks$ = new Subject<Observable<any>>();
  remover$ = of('').pipe(
    delay(environment.delayTime),
    tap(() => this.messages.shift())
  );
...
    this.tasks$.pipe(mergeMap(task => task)).subscribe();
    this.message$
      .pipe(tap(value => this.messages.push({ ...value })))
      .subscribe(value => {
        this.tasks$.next(this.remover$);
      });

給你參考看看

參考文件: https://github.com/ReactiveX/rxjs/blob/master/doc/marble-testing.md

1個讚