RxJs Marble使用withLatestFrom测试concatMap

问题描述

如何对该可观察对象进行单元测试?

e1.pipe(
    concatMap(x => of(x).pipe(withLatestFrom(e2)))
);

以下单元测试失败:

        it('test',() => {
            const e1 = hot(       '--1^---2----3-|');
            const e2 = hot(       '-a-^-b-----c--|');
            const expected = cold(   '----x----y-|',{
                x: ['2','b'],y: ['3','c']
            });

            const result = e1.pipe(
                concatMap(x => of(x).pipe(
                    withLatestFrom(e2))
                )
            );

            // but this works:
            // const result = e1.pipe(withLatestFrom(e2));

            expect(result).toBeObservable(expected);
        });

如何通过测试才能书写大理石?我做错了什么? 我希望通过将concatMap运算符插入到链中(在withLatestFrom之前),我还必须以某种方式在大理石上对其进行“标记”。

解决方法

在您的 real 示例中

e1.pipe(
  concatMap(x => of(x).pipe(withLatestFrom(e2)))
);

一切正常,可能是因为BehaviorSubjectReplaySubject,在您的测试中情况并非如此。

尽管您正在使用hot( '-a-^-b-----c--|');,但这并不意味着您正在使用BehaviorSubject。如果我们查看implementation,我们会看到HotObservable扩展了Subject类:

export class HotObservable<T> extends Subject<T> implements SubscriptionLoggable { /* ... */ }

这应该有助于了解其工作原理:

const result = e1.pipe(withLatestFrom(e2));

这不是:

const result = e1.pipe(
    concatMap(x => of(x).pipe(
        withLatestFrom(e2))
    )
);

在第一个代码段中,e2被订阅。在第二篇文章中,由于您使用的是e1,因此concatMap每次发出时,e1都会被订阅,然后由于{ {1}}。

考虑到这一点,这就是我的方法:

注意:我正在使用withLatestFrom(e2))

提供的内置功能
complete