简体   繁体   中英

Mock out http request of service class in a jasmine test

I was under the impression that you could just spy on services in jasmine using the spyOn method. And then return a value once that method is called. But maybe that's too simplistic of a thought?

I would like to test the following nxjs action:

./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
        });
      })
    );
  }

That action depends on the authService login method:

./auth.service.ts

  // ...

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

Now my test is as follows:

./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);
    });
  });
  // ...

In your Auth.state.spec.ts file, you should get instance of injected service from angular's 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();
      
      ....
    });
  });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM