【问题标题】:Testing NGRX effect that emits action with delay OR does not emit anything测试 NGRX 效果,延迟发出动作或不发出任何东西
【发布时间】:2021-04-16 15:53:56
【问题描述】:

我有一个 NGRX 效果 - 根据状态 - 发出延迟的动作或什么也不发出。 我想写一个测试,涵盖这两种情况。

这是效果:

myEffect$ = createEffect(() =>
  this.actions$.pipe(
    ofType(MyAction),
    filter(state => state.foo === false),
    delay(4000),
    map(state => myOtherAction())
  )
);

对于它应该发出有延迟的 otherAction 的情况的测试工作正常:

describe('emit my action', () => {
   const action = MyAction();

   it('should return a stream with myOtherAction', () => {
      const scheduler = getTestScheduler();
      scheduler.run(helpers => {
        // build the observable with the action
        actions = hot('-a', { a: action });

        // define what is the expected outcome of the effect
        const expected = {
           b: MyOtherAction()
        };
        helpers.expectObservable(effects.myEffect$).toBe('- 4000ms b', expected);
      });
   });
});

但我不知道如何测试另一个状态,它应该不发出另一个动作(流的长度为零):

   it('should return an empty stream', () => {
      store.setState({
        myFeature: {
           foo: true
        }
      });
      // ???
   });

请帮忙:)

【问题讨论】:

    标签: jasmine ngrx-effects jasmine-marbles rxjs-marbles ngrx-test


    【解决方案1】:

    这将很难做到,因为过滤器会阻止效果返回可观察对象。

    选项 1: // 无论你在哪里调度 MyAction,只有在创建的动作的 foo 属性为 true 时才调度它

    选项 2: // 改变效果的结构以返回空

    import { EMPTY } from 'rxjs';
    ....
    myEffect$ = createEffect(() =>
      this.actions$.pipe(
        ofType(MyAction),
        delay(4000),
        map(state => state.foo ? myOtherAction() : EMPTY)
      )
    );
    

    测试:

    import { EMPTY } from 'rxjs';
    ....
    describe('emit my action', () => {
       const action = MyAction();
       action.foo = false; // set foo property to false
    
       it('should return a stream with myOtherAction', () => {
          const scheduler = getTestScheduler();
          scheduler.run(helpers => {
            // build the observable with the action
            actions = hot('-a', { a: action });
    
            // define what is the expected outcome of the effect
            const expected = {
               b: EMPTY // assert now it is empty
            };
            helpers.expectObservable(effects.myEffect$).toBe('- 4000ms b', expected);
          });
       });
    })
    

    【讨论】:

    • 选项 2 至少对我来说是最好的提示。然而,返回 EMPTY 让 linter 抱怨“Observable | Observable>' 不能分配给类型 'Observable”,但我引入了一个“Noop Action”并改为返回。
    【解决方案2】:

    由于 AliF50 的提示,我将链中的 filter 替换为“Noop Action”(= 没有任何侦听器的正常操作)。因此,我没有检查过滤器中的 foo 属性,而是在 foo 为真时返回映射中的 noopAction,当它为假时返回 otherAction。

    效果:

    myEffect$ = createEffect(() =>
      this.actions$.pipe(
        ofType(MyAction),
        //filter(state => state.foo === false),
        delay(4000),
        map(state => state.foo !== false ? noopAction() : myOtherAction())
      )
    );
    

    测试:

    describe('emit my action', () => {
      const action = MyAction();
    
      it('should return a stream with myOtherAction', () => {
        const scheduler = getTestScheduler();
        scheduler.run(helpers => {
          // build the observable with the action
          actions = hot('-a', { a: action });
          // define what is the expected outcome of the effect
          const expected = {
            b: MyOtherAction()
          };
          helpers.expectObservable(effects.myEffect$).toBe('- 4000ms b', expected);
        });
      });
    
      it('should return a stream with noop action as foo is true', () => {
        store.setState({
          myFeature: {
            foo: true
          }
        });
        const scheduler = getTestScheduler();
        scheduler.run(helpers => {
          // build the observable with the action
          actions = hot('-a', { a: action });
          // define what is the expected outcome of the effect
          const expected = {
            b: NoopAction()
          };
          helpers.expectObservable(effects.myEffect$).toBe('- 4000ms b', expected);
        });
      });
    
    });
    

    【讨论】:

      猜你喜欢
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多