在茉莉花测试中模拟服务 class 的 http 请求

Mock out http request of service class in a jasmine test

我的印象是您可以使用 spyOn 方法监视 jasmine 中的服务。然后 return 调用该方法后的值。但也许这是一个过于简单化的想法?

我想测试以下 nxjs 操作:

./Auth.state.ts

  // ...

  @Action(Login)
  login(ctx: StateContext<AuthStateModel>, action: Login) {
    return this.authService.login(action.payload).pipe(
      tap(({ accessToken }: { accessToken: string }) => {
        const {exp} = jwt_decode(accessToken);
        const expiresAt = dayjs().add(exp, 'second');
        ctx.patchState({
          token: accessToken,
          username: action.payload.username,
          expiresAt
        });
      })
    );
  }

该操作取决于 authService 登录方法:

./auth.service.ts

  // ...

  login({ username, password }: User): Observable<{ accessToken?: string }> {
    return this.http
      .post(`${api.BASEURL}${api.API_LOGIN}`, { username, password });
  }

现在我的测试如下:

./Auth.state.spec.ts

describe('Auth', () => {
  let store: Store;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [NgxsModule.forRoot([AuthState]), HttpClientTestingModule],
      providers: [HttpClient, HttpHandler, AuthService]
    });

    store = TestBed.inject(Store);
  });

  function setupState(NEW_STATE = null) {
    store.reset({
      ...store.snapshot(),
      auth: NEW_STATE
    });
  }

  describe('login', () => {
    it('sets the state when login is successful', () => {
      // TS2345: Argument of type '"register"' is not assignable to parameter of type 'never'.
      spyOn(AuthService, 'login').and.returnValue(false);

      // read an workaround for it here: https://github.com/facebook/jest/issues/9675 
      // Object.defineProperty(AuthService, 'login', { get(){ return false; } });
      // but also no luck...

      const expectedState = { token: null, username: 'Some username', expiresAt: null };
      setupState();
      store.dispatch(new Login({ username: expectedState.username, password: '' }));
    
      const auth = store.selectSnapshot(state => state.auth);
      expect(auth).toEqual(expectedState);
    });
  });
  // ...

在您的 Auth.state.spec.ts 文件中,您应该从 angular 的 TestBed 中获取注入服务的实例。

describe('login', () => {
   it('sets the state when login is successful', () => {
      // Get the injected instance of AuthService
      const authService = TestBed.inject(AuthService);

      spyOn(authService, 'register').and.returnValue(of(false));

      spyOn(authService, 'login').and.returnValue(
        of({ access_token: 'scdkj2' })
      );
      // Make sure fixture.detectChanges() is not invoked before all spies are setup
      fixture.detectChanges();
      
      ....
    });
  });