RXJS大理石测试

问题描述

我对 mergemap 进行了测试,但它没有返回正确的预期结果。有人可以帮我吗?

谢谢!

it("should maps to inner observable and flattens",() => {
      const values = { a: "hello",b: "world",x: "hello world" };
      const obs1 = cold(    "-a---a|",values);
      const obs2 = cold(    "-b-b-b-|",values);
      const expected = cold("--x-xxxx-x-|",values);

      const result = obs1.pipe(mergeMap(x => obs2.pipe(map(y => x + " " + y))));
      expect(result).toBeObservable(expected);

解决方法

我会尝试分解您的测试,以便您了解正在发生的事情以及您做错了什么。非常抱歉,我不会使用 jasmine-marbles 库,而是使用 preferred way of writing tests(我还建议您避免使用 jasmine-marbles 库)。

当转换为普通的旧弹珠(不使用 jasmine-marbles 库)时,您的测试如下所示:

import { mergeMap,map } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/testing';

describe('mergeMap',() => {
  let testScheduler: TestScheduler;

  beforeEach(() => {
    testScheduler = new TestScheduler(someMatcher);
  });

  it('should maps to inner observable and flattens',() => {
    testScheduler.run(({ cold,expectObservable }) => {
      const values = { a: 'hello',b: 'world',x: 'hello world' };
      const obs1 = cold('-a---a|     ',values);
      const obs2 = cold('-b-b-b-|    ',values);
      const expected = ' --x-xxxx-x-|';

      const result = obs1.pipe(mergeMap(x => obs2.pipe(map(y => x + ' ' + y))));
      expectObservable(result).toBe(expected,values);
    });
  });
});

这个测试失败了。原因如下:您希望您的测试在第 2、4、5、6、7、9 帧发射,并在第 11 帧完成。但是,实际发射发生在第 2、4、6、6、8 帧, 10 和第 12 帧的完整内容。现在,为了能够直观地理解为什么以及如何发生这种情况,我将编写一个带有几个注释的测试,并将它们以不同的方式对齐,以便您更好地了解发生的情况:

const obs1 = cold('-a---a|      ',values);
const obs2 = cold(' -b-b-b-|    ',values);
//                      -b-b-b-|
const expected = ' --x-xxxx-x-| ';
// frames:         0123456789012

基本上,在 mergeMap 中,当源 observable 发出时,您将返回 obs2 的实例。在这种情况下,源是 obs1。当它发出第一个值 (a) 时,在第 1 帧,mergeMap 在内部订阅 obs2 - 这就是为什么我将 obs2 排放的开始对齐到低于 { {1}} 在第 1 帧。来自 a 的排放物是到达消费者的排放物。

类似地,当 obs2 发出第二个值时,在第 5 帧,另一个订阅 obs1 发生,并且由于 obs2 是一个 obs2 可观察对象,因此另一个生产者被实例化,所以另一个流开始流动。这就是为什么我添加了一条评论来指示第二次订阅 cold 的时间。它从第 5 帧开始,就在第二个 obs2a 发出时。同样,第二个订阅 obs1 的排放是到达消费者的排放。

因此,结合这一点,我们得出预期帧应该在哪里的结论:

obs2

基于此,最终的排放发生在第 2、4、6、6、8 和 10 帧,完成发生在第 12 帧。这种设置的问题是无法显示提前到来的排放在同一帧出现两次或多次发射之后。

也就是说,第 8 帧的发射与第 6 帧的两个发射太接近了。原因是发生在同一帧的发射在大理石图中用括号 -b-b-b-| emits at frames: 2,4 and 6 and a complete at frame 8 -b-b-b-| emits at frames: 6,8 and 10 and a complete at frame 12 0123456789012 分组,括号是在某种程度上隐藏了一些排放量。这是你的情况:

()

第 7、8 和 9 帧被隐藏且无法表示,因此无论如何都无法在弹珠图中显示这些帧的排放。而且,由于第 8 帧的发射丢失了,因此您无法为该预期发射创建合适的弹珠图。

为了让此测试通过,您可以在第 6 帧从 -b-b-b-| -b-b-b-| --x-x-(xx)x-| // brackets start at frame 6 and represent grouped emissions which all happen at frame 6 0123456666012 // the frames 7,8 and 9 are "hidden" 进一步发出第二个 a。现在,您的测试可能如下所示(现在应该通过):

obs1