如何为 redux-observalbe Epic 中使用的自定义 RxJS 运算符编写大理石测试

How to write marble test for this custom RxJS operator used in redux-observalbe Epic

我需要为我在这个 loadEpic 史诗中使用的自定义运算符编写大理石测试 - 这有助于我避免操作 INITIALiZE 有时被调度到延迟并且我得到 LOAD_FAILURE:

loadEpic: Epic<ExamManagementAction, ExamManagementAction, RootState> = (
    action$,
    state$
  ) =>
    action$.pipe(
      filter(isActionOf(load)),
      waitFor(state$),
      switchMap(() =>
        this.load(state$).pipe(
          map(loadSuccess),
          catchError(error => of(loadFailure({ error })))
        )
      )
    );

这就是我编写 waitFor 运算符的方式,效果很好:

const waitFor = <T>(
  state$: Observable<RootState>
): OperatorFunction<T, T> => source$ =>
  source$.pipe(
    switchMap(value =>
      state$.pipe(
        filter(state => state.navigation.initialized),
        take(1),
        mapTo(value)
      )
    )
  );

你能帮我用 rxjs-marbles/jest 或任何类似的方法编写这个测试吗?非常感谢!

您描述了三个事件流:

  1. 状态(用简单的对象模拟它们)
  2. actions(同样,您可以使用任何 JS 值作为模拟)
  3. 已过滤的操作(与 2 中的对象相同)

然后您希望您的运算符使用 toBeObservable 匹配器将 2 转换为 3。就是这样。

  it('should reject given values until navigation is initialized', () => {
    const state$ = hot('   -i--u--u-i--  ', {u: {navigation: {initialized: false}}, i: {navigation: {initialized: true}}});
    const action$ = hot('  v----v--v---  ', {v: load});
    const expect$ = cold(' -v-------v--  ', {v: load});

    expect(action$.pipe(waitFor(state$))).toBeObservable(expect$);
  });

请注意我如何格式化我的代码,以便一个流在另一个流下进行描述。它确实有助于处理长事件序列。

您也可以为边缘情况编写单独的规范。这取决于您要测试的行为。