【问题标题】:@ngrx/effects: testing an effect returns empty()@ngrx/effects:测试效果返回 empty()
【发布时间】:2018-06-16 15:49:13
【问题描述】:

我正在使用@ngrx/effects 4.1.1。我有一个像这样返回一个空的 observable 的效果:

@Effect() showDialog$: Observable<Action> = this
.actions$
.ofType( ActionTypes.DIALOG_SHOW )
.map( ( action: DialogAction ) => action.payload )
.switchMap( payload => {
    this.dialogsService.showDialog( payload.className );
    return empty();
} );

我正在尝试在these guidelines 之后编写一个单元测试,以测试该效果是否会产生一个空的 observable。我有这个:

describe( 'DialogEffects', () => {
    let effects: DialogEffects;
    let actions: Observable<any>;
    const mockDialogService = {
        showDialog: sinon.stub()
    };

    beforeEach( () => {
        TestBed.configureTestingModule( {
            providers: [
                DialogEffects, provideMockActions( () => actions ),
                {
                    provide: DialogsService,
                    useValue: mockDialogService
                }
            ]
        } );

        effects = TestBed.get( DialogEffects );
    } );

    describe( 'showDialog$', () => {
        it( 'should return an empty observable', () => {
            const dialogName = 'testDialog';
            const action = showDialog( dialogName );

            actions = hot( '--a-', { a: action } );
            const expected = cold( '|' );

            expect( effects.showDialog$ ).toBeObservable( expected );
        } );
    } );
} );

但是,Karma (v1.7.1) 抱怨:

预期 [ ] 等于 [ Object({ frame: 0, notification: Notification({ kind: 'C', value: undefined, error: undefined, hasValue: false }) }) ]。

如何测试效果返回empty()?我曾尝试使用dispatch: false 修改效果元数据,但这没有效果。

想法?

【问题讨论】:

  • 你的效果不会完成,所以你的冷观察应该是cold(''); - 管道字符代表观察流的完成。
  • 感谢卡坦特,现在可以了!你应该发布它,我会标记为已解决。
  • 我认为 empty() 会立即完成。
  • switchMap 看到空的 observable(是的,它确实完成了)合并到 effect obsevable 中。可观察的效果没有完成。基本上,你永远不想完成一个可观察的效果。如果效果完成,它会停止响应操作。
  • 那么如果将完成的空 observable 合并到 effect observable 中,为什么 effect observable 在遇到这个空 observable 的 complete 时没有完成?

标签: angular unit-testing karma-jasmine ngrx-effects


【解决方案1】:

要测试该效果不会调度,您可以使用getEffectsMetadata 函数对其元数据进行断言:

expect(getEffectsMetadata(effects).deleteSnapshotSuccess$?.dispatch).toBe(false)

以上内容已使用 ngrx 9.0.0 进行测试。由于无论dispatch 是什么,所有可观察对象都会发出,因此像expect(effects.effect$).toBeObservable(cold('')) 这样的检查不会产生预期的结果。

【讨论】:

    【解决方案2】:

    最好的方法是在效果中使用 dispatch false 并更改 swicthMap 以进行点击

    @Effect({dispatch: false}) showDialog$ = this.actions$.pipe(
       ofType( ActionTypes.DIALOG_SHOW ),
       map( ( action: DialogAction ) => action.payload ),
       tap( payload => 
          this.dialogsService.showDialog( payload.className )
        ));
    

    要测试它,你可以这样做

    describe( 'showDialog$', () => {
        it( 'should return an empty observable', () => {
            const dialogName = 'testDialog';
            const action = showDialog( dialogName );
            actions = hot( '--a-', { a: action } );
    
           expect(effects.showDialog$).toBeObservable(actions);
    // here use mock framework to check the dialogService.showDialog is called
        } );
    } );
    

    请注意我使用 toBeObservable(actions) 的原因,因为由于 disptach false 这个效果不会产生任何东西,所以动作和以前一样,你通过调用 toBeObservable(actions) 获得的是使测试同步,所以你可以在它之后检查你的服务是使用 jasmine 或 ts-mockito 等模拟框架调用的

    【讨论】:

    • 您知道如何验证{ dispatch: false } 是否存在。当 { dispatch: false } 从效果中移除时,您答案中的测试仍然会通过。
    • 是的,对于 Angular 8 之前的版本,您有 v7.ngrx.io/guide/effects/testing#geteffectsmetadata,要检查这一点,但据我所知,这仅适用于 @Effect,在 8 中推荐的方法是使用 createEffect 而不确定 getEffectsMetadata文档中省略了它的工作原理
    • 有趣的事实:我们正在使用 Angular 和 NgRx 8...所以问题仍然存在,我们如何测试它?
    • 嘿,我只是碰巧使用 createEffect 测试了具有角度 8 效果的 getEffectsMetadata,它仍然有效,不知道为什么不再出现在文档中。
    • 届时我们也会尝试!感谢您的帮助!
    【解决方案3】:

    问题是您将实际结果与cold('|') 进行比较。

    cold('|') 中的管道字符表示可观察流的完成。但是,您的效果不会完成。 empty() observable 确实完成了,但从 switchMap 返回 empty() 只会看到 observable 合并到 effect observable 的流中 - 它没有完成 effect observable。

    相反,您应该将实际结果与 cold('') 进行比较 - 一个不发出任何值且未完成的 observable。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 2018-10-05
      相关资源
      最近更新 更多