@ ngrx / effects:测试一个效果返回empty()

时间:2018-01-07 12:43:23

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

我正在使用@ 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:&#39; C&#39;,value:undefined,error:undefined,hasValue:false})})]。< / p>

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

想法?

3 个答案:

答案 0 :(得分:5)

问题是您要将实际结果与200px进行比较。

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

相反,您应该将实际结果与switchMap进行比较 - 一个不会发出任何值但未完成的观察结果。

答案 1 :(得分:1)

做到这一点的最佳方法是在效果中使用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 );
      return empty();
   } ));

要进行测试,您可以像

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导致此效果不会产生任何结果,因此action与以前相同,通过调用toBeObservable(actions)获得的结果是使测试同步,因此您可以在之后检查您的服务是否已通过茉莉或ts-mockito之类的模拟框架进行调用

答案 2 :(得分:1)

要测试效果是否未调度,可以使用getEffectsMetadata函数针对其元数据进行断言:

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

以上已通过ngrx 9.0.0测试。由于所有可观察物都发出而与dispatch无关,因此expect(effects.effect$).toBeObservable(cold(''))之类的检查不会产生预期的结果。