ngrx 测试效果动作失败

Posted

技术标签:

【中文标题】ngrx 测试效果动作失败【英文标题】:ngrx testing effects action failure 【发布时间】:2022-01-15 08:19:34 【问题描述】:

我有这个效果

login$ = createEffect(() =>
    this.actions$.pipe(
      ofType(AuthActions.login),
      exhaustMap((action) =>
        this.service.login(action.credentials).pipe(
          map((data: LoginResponseDto) => 
            localStorage.setItem('__AUTH__', JSON.stringify(data));
            return AuthActions.loginSuccess( data );
          ),
          catchError((error: ErrorDto) => 
            return of(AuthActions.loginFailure( error ));
          )
        )
      )
    )
  );

我能够测试 loginSucces 但不能 登录失败

describe('login$', () => 
    it('should handle login and return a loginSuccess action', () => 
      const action = AuthActions.login( credentials: loginRequestPayload );
      const outcome = AuthActions.loginSuccess( data: loginSuccessPayload );

      testScheduler.run((helpers: RunHelpers) => 
        const  cold, expectObservable, hot  = helpers;
        actions = hot('-a',  a: action );
        const response = cold('-b|',  b: loginSuccessPayload );
        authService.login.and.returnValue(response);

        expectObservable(effects.login$).toBe('--b',  b: outcome );
      );
    );
    it('should handle login and return a loginFailure action', () => 
      const action = AuthActions.login( credentials: loginRequestPayload );
      const outcome = AuthActions.loginFailure( error: loginFailurePayload );

      testScheduler.run((helpers: RunHelpers) => 
        const  cold, expectObservable, hot  = helpers;
        actions = hot('-a',  a: action );
        const response = cold('-#|', , loginFailurePayload);

        authService.login.and.throwError(response);

        expectObservable(effects.login$).toBe('--(b|)',  b: outcome );
      );
    );
  );

我收到了这条消息:

Expected $.length = 1 to equal 2. Expected $[0].frame = 1 to equal 2.
Expected $[0].notification.kind = 'E' to equal 'N'. Expected $[0].notification.value = undefined to equal Object( error: Object(
message: 'Error' ), type: '[Auth Api] Login Failure' ). Expected
$[0].notification.error = null( _subscribe: Function, messages: [
Object( frame: 1, notification: Object( kind: 'E', value: undefined,
error: Object( message: 'Error' ) ) ), Object( frame: 2,
notification: Object( kind: 'C', value: undefined, error: undefined
) ) ], subscriptions: [  ], scheduler: TestScheduler(
schedulerActionCtor: Function, now: Function, actions: [  ], _active:
false, _scheduled: undefined, maxFrames: Infinity, frame: 1, index: 1,
assertDeepEqual: Function, hotObservables: [  ], coldObservables: [
<circular reference: Object> ], flushTests: [ Object( actual: [
Object( frame: 1, notification: Object( kind: 'E', value: undefined,
error: <circular reference: Object> ) ) ], ready: true, expected: [
Object( frame: 2, notification: Object( kind: 'N', value: Object(
error: Object, type: '[Auth Api] Login Failure' ), error: undefined
) ), Object( frame: 2, notification: Object( kind: 'C', value:
undefined, error: undefined ) ) ] ) ], runMode: true ) ) to equal
undefined. Expected $[1] = undefined to equal Object( frame: 2,
notification: Object( kind: 'C', value: undefined, error: undefined
) ).

更新

这行得通

it('should handle login and return a loginFailure action', () => 
      const action = AuthActions.login( credentials: loginRequestPayload );
      const outcome = AuthActions.loginFailure( error: loginFailurePayload );

      testScheduler.run(( cold, expectObservable, hot : RunHelpers) => 
        actions = hot('-a',  a: action );
        const response = cold('-#|', , loginFailurePayload);
        authService.login.and.returnValue(response);
        expectObservable(effects.login$).toBe('--b',  b: outcome );
      );
    );

【问题讨论】:

【参考方案1】:

如果没有看到实现就很难说,我的猜测是发出值的时间存在一些差异。另外,我猜效果不会完成,所以预期的大理石应该是--b

另外,我不喜欢使用大理石语法来测试效果,因为它们可能对时间不敏感 - 请参阅我的 blog post 以获取替代方法。

【讨论】:

以上是关于ngrx 测试效果动作失败的主要内容,如果未能解决你的问题,请参考以下文章

ngrx 调度的动作未达到效果

ngrx 效果:由一个效果调度的动作是不是立即被其他效果处理?

Action ngrx 4 的测试用例

NGRX - 使用 jasmine-marbles 将 Promise 转换为 observables 的测试效果问题

在调度一个动作和 NgRx 效果之前执行多个 API 调用

单元测试茉莉花@NGRX/DATA