【问题标题】:Observable.fromPromise empty during unit testingObservable.fromPromise 在单元测试期间为空
【发布时间】:2018-02-16 19:40:31
【问题描述】:

loadAdList$ 是一个接入actions$ 流的 Observable:

loadAdList$: Observable<Action> = this.actions$
    .ofType<adActions.Load>(adActions.LOAD)
    .switchMap((action) => {
      return Observable.fromPromise(store.findAll('ad', action.payload)
        .then((ads) => {
          return new adActions.LoadSuccess(ads);
        })
        .catch((err) => {
          return new adActions.LoadFail(err);
        }));
    });

它在浏览器中工作,没有问题。但是,我也想对其进行单元测试:

actions$ = hot('-a', { a: loadAction });
const storeResponse = Promise.resolve(mockAds);
const expected$ = cold('-c', { c: loadSuccessAction });

spyOn(store, 'findAll').and.returnValue(storeResponse);

expect(effects.loadAdList$).toBeObservable(expected$);

测试失败并显示以下内容:

Expected 

to deep equal 
    {"frame":10,"notification":{"kind":"N","value":{"payload":"[
    ...

我认为这个问题与返回承诺的 store.findAll 方法有关。这是基于以下测试的结果:

.switchMap((action) => {
  // This test will pass
  return Observable.from([new adActions.LoadSuccess(mockAds)]);

  // This test will fail
  return Observable.fromPromise(Promise.resolve(new adActions.LoadSuccess(mockAds)));

});

【问题讨论】:

  • Promise.resolve 总是异步解析,而 RxJS TestScheduler - 支持 hotcold - 使用虚拟时间并且是同步的。出于这个原因,我怀疑 Promise 是否可以用于大理石图测试,但我可能是错的。至少,您的测试必须是异步的,并且不清楚它是否是异步的。
  • 如果你想要一个异步测试运行器,我强烈推荐 blue-tape。

标签: typescript promise jasmine observable


【解决方案1】:

这有点不幸,但是在 Rx v5 的 TestScheduler 的上下文中,并没有很好的方法来同步解决 Promise。出于这些原因,如果 Observable 源从 promise 开始,它将不适用于大理石测试,并且您必须通过订阅来创建不同的断言。

如果您想详细了解失败的原因,请查看https://github.com/ReactiveX/rxjs/issues/701 / https://github.com/ReactiveX/rxjs/pull/745

【讨论】:

  • 虽然很好理解,但是很烂。这基本上意味着,如果您在任何 RXJS 链中使用 from() 或 NGRX @effects,则必须使用混合测试方法来编写测试,因为使用 Promises 使弹珠测试变得不可能。
  • @MichaelTrouw 你总是可以模拟返回 Promise 的函数以返回 of(...),尽管我很欣赏这并不总是会产生预期的效果。
  • @hevans900 是的,当然,这很好。但是如果你想测试一个复杂的可观察链,它内部某处使用from()?好了,你现在不能再使用大理石测试了。也不是一个大问题,但事实上你需要知道你不能,我会说,是。换句话说:假设您不想测试结果/结果,因为它用于组件或其他地方,您想测试可观察链本身。
  • @MichaelTrouw 不,你确实可以弹珠测试 Observables 的链,中间有 from(somePromise),你只需要模拟 somePromise 来返回 of(...)。我有它在我面前工作,如果你愿意,很高兴向你发送 github gist。这是有效的,因为from 的底层实现首先对参数进行类型检查以查看它是否是 Observable,如果是,则避免任何转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多