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

ser*_*gpa 4 unit-testing karma-jasmine ngrx-effects angular

我正在使用@ 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();
} );
Run Code Online (Sandbox Code Playgroud)

我正在尝试按照这些指南编写一个单元测试,测试该效果会产生一个空的可观察量.我有这个:

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 );
        } );
    } );
} );
Run Code Online (Sandbox Code Playgroud)

然而,Karma(v1.7.1)抱怨说:

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

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

想法?

car*_*ant 6

问题是你要比较实际结果cold('|').

管道字符in cold('|')表示可观察流的完成.但是,您的效果将无法完成.在empty()观察到的不完整,但返回empty()switchMap刚才看到的是观察到合并到效果观察到的流-它不完全观察到的效果.

相反,您应该将实际结果与cold('')- 一个不发出值但未完成的可观察量进行比较.


Gab*_*ero 6

最好的方法是在效果中使用 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 )
    ));
Run Code Online (Sandbox Code Playgroud)

要测试它,你可以这样做

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
    } );
} );
Run Code Online (Sandbox Code Playgroud)

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