angular - ngrx 测试方法调度 Action

标签 angular unit-testing jasmine

我有一个包含方法的服务,调用时将调度一个 Action

export default class AuthService {
  constructor(private store: Store<IAppState>, private jwtService: JWTService) {}

  public isSessionValid = (id_token?: string, access_token?: string): Observable<boolean> => {
    const hasValidSession: boolean = this.jwtService.isTokenValid(id_token);

    if (!hasValidSession) {
      this.invalidateSession();
      return of(false);
    }

    this.setupValidSession(id_token, access_token);
    return of(true);
  }

  public invalidateSession = (): void => {
    this.store.dispatch(new InvalidSession());
  }

  public setupValidSession = (id_token?: string, access_token?: string): void => {
    this.store.dispatch(new ValidSession());

    if (id_token && access_token) {
      this.store.dispatch(
        new PersistSessionTokens({
          [ID_TOKEN_STORAGE_KEY]: id_token,
          [ACCESS_TOKEN_STORAGE_KEY]: access_token,
        })
      );
    }
  }
}

我想在我的测试中断言,如果 invalidateSession被调用,一个 Action 被分派(dispatch)。

然而,我尝试编写测试返回 Expected spy dispatch to have been called.
我的规范文件
import { TestBed } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

import AuthService from './auth.service';
import JWTService from '../jwt/jwt.service';
import { Store } from '@ngrx/store';

describe('AuthService', () => {
  describe('isSessionValid', () => {
    it('should call isTokenValid on the jwtService with an id_token', () => {
      const { authService, jwtService, props } = setup({ id_token: '123' });
      const jwtServiceSpy = spyOn(jwtService, 'isTokenValid');
      authService.isSessionValid(props);

      expect(jwtServiceSpy).toHaveBeenCalledWith({ id_token: '123' });
    });

    it('should call invalidateSession if hasValidSession is false', () => {
      const { authService, jwtService, props } = setup({});
      spyOn(jwtService, 'isTokenValid').and.returnValue(false);
      const authServiceInvalidSessionSpy = spyOn(authService, 'invalidateSession');
      authService.isSessionValid(props);

      expect(authServiceInvalidSessionSpy).toHaveBeenCalled();
    });

    it('should call setupValidSession if hasValidSession is true', () => {
      const { authService, jwtService, props } = setup({});
      spyOn(jwtService, 'isTokenValid').and.returnValue(true);
      const authServicehasValidSessionSpy = spyOn(authService, 'setupValidSession');
      authService.isSessionValid(props);

      expect(authServicehasValidSessionSpy).toHaveBeenCalled();
    });
  });

  describe('invalidateSession', () => {
    it('should dispatch the InvalidSession action', () => {
      const { authService, jwtService, props, store } = setup({});

      spyOn(jwtService, 'isTokenValid').and.returnValue(false);
      const authServiceInvalidSessionSpy = spyOn(authService, 'invalidateSession');
      const storeSpy = spyOn(store, 'dispatch');
      authService.invalidateSession();

      expect(storeSpy).toHaveBeenCalled();
    });
  });

  const setup = propOverrides => {
    TestBed.configureTestingModule({
      providers: [
        AuthService,
        {
          provide: JWTService,
          useClass: MockJWTService,
        },
        { provide: Store, useClass: MockStore },
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    }).compileComponents();

    const props = Object.assign({}, { ...propOverrides });

    const authService = TestBed.get(AuthService);
    const jwtService = TestBed.get(JWTService);
    const store = TestBed.get(Store);

    return { authService, jwtService, props, store };
  };
});

export class MockJWTService {
  isTokenValid(id_token?: string) {}
}

export class MockStore {
  select() {}
  dispatch() {}
}

我试图在 invalidateSession 中测试它描述块

最佳答案

在你的例子中,问题是你 mock 了 spyOn(authService, 'invalidateSession'); ,因此它的原始逻辑没有被调用,因此没有调度。

对于此类测试,我通常使用 ng-mocks
它允许通过几次调用来设置模拟环境。

beforeAll(() => MockBuilder(
  AuthService,
  [AuthServiceModule, StoreModule.forRoot({})],
));

it('dispatches an action', () => {
  const dispatchSpy = MockInstance(
    Store,
    'dispatch',
    jasmine.createSpy(),
  );

  const service = TestBed.inject(AuthService);
  const store = TestBed.inject(Store);

  service.invalidateSession();
  expect(dispatchSpy).toHaveBeenCalledWith(
    new InvalidSession(),
  );
});

关于angular - ngrx 测试方法调度 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50860228/

相关文章:

angular - 如何在 Angular2 Outlook 插件中使用插件命令

java - 如何在 Java 应用程序中测试私有(private)构造函数?

javascript - 如何正确地对按钮点击进行 Jasmine 测试

javascript - 在 Angular 2 中为 infoWindow 设置点击监听器

angular - 我什么时候应该使用 TS 在 Angular 2+ 中导入类型?

html - Angular 6 - 从 httpClient 获取 csv 响应

node.js - Bluebird、Jasmine 和异步函数未处理的拒绝错误

java - 如何创建 ArchUnit 规则来验证引发的所有异常是否继承自特定的自定义异常?

c++ - 对二叉搜索树进行单元测试

ruby-on-rails - 哪个 gem 应该用于使用Rails jasminerice或Jasmine-rails或Teaspoon测试JavaScript?