如何测试使用NGRX的角度服务

时间:2019-05-11 08:34:46

标签: angular unit-testing testing karma-jasmine ngrx

我有以下服务:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { auth } from 'firebase/app';
import { AngularFireAuth } from '@angular/fire/auth';
import { Store } from '@ngrx/store';
import * as fromRoot from '../app.reducer';
import * as  Auth from './auth.actions';

@Injectable({
    providedIn: 'root'
})
export class AuthService {

    constructor(public afAuth: AngularFireAuth, public router: Router, private store: Store<fromRoot.State>) {
        this.afAuth.authState.subscribe(user => {
            if (user) {
                this.store.dispatch(new Auth.SetAuthenticated(user));
            } else {
                this.store.dispatch(new Auth.SetUnauthenticated());
                this.router.navigate(['auth/login']);
            }
        });
    }

    async login(email: string, password: string) {
        return await this.afAuth.auth.signInWithEmailAndPassword(
            email,
            password
        );
    }
    async register(email: string, password: string) {
        return await this.afAuth.auth.createUserWithEmailAndPassword(
            email,
            password
        );
    }

    async sendPasswordResetEmail(passwordResetEmail: string) {
        return await this.afAuth.auth.sendPasswordResetEmail(
            passwordResetEmail
        );
    }
    async logout() {
        await this.afAuth.auth.signOut();
    }
    async loginWithGoogle() {
        return await this.afAuth.auth.signInWithPopup(new auth.GoogleAuthProvider());
    }
}

我正在尝试在auth.service.specs.ts中对其进行测试:

import { TestBed, inject } from '@angular/core/testing';

import { AuthService } from './auth.service';
import { BehaviorSubject } from 'rxjs';
import { AngularFireAuth } from '@angular/fire/auth';
import { RouterTestingModule } from '@angular/router/testing';
import { TestStore } from '../test/testStore';
import { Store } from '@ngrx/store';
import * as fromRoot from '../app.reducer';
import { User } from 'firebase';

const FirestoreStub = {
    collection: (name: string) => ({
      doc: (_id: string) => ({
        valueChanges: () => new BehaviorSubject({ foo: 'bar' }),
        set: (_d: any) => new Promise((resolve, _reject) => resolve()),
      }),
    }),
  };

  let store: TestStore<fromRoot.State>;

describe('AuthService', () => {
     // An anonymous user
  const authState: User = {
    displayName: null,
    isAnonymous: true,
    uid: '17WvU2Vj58SnTz8v7EqyYYb0WRc2'
  };

  beforeEach(() => TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    providers: [
        { provide: AngularFireAuth, useValue: FirestoreStub },
        { provide: Store, useClass: TestStore }   // use test store instead of ngrx store
      ],
  }));
  beforeEach(inject([Store], (testStore: TestStore<fromRoot.State>) => {
    store = testStore;                            // save store reference for use in tests
    store.setState({auth: {isAuthenticated:false, user:null}}); // set default state
  }));

  it('should be created', () => {
    const service: AuthService = TestBed.get(AuthService);
    expect(service).toBeTruthy();
  });
});

目前,我什至无法创建此文件:

HeadlessChrome 74.0.3723 (Windows 10.0.0) AuthService should be created FAILED
        TypeError: Cannot read property 'subscribe' of undefined
            at new AuthService (src/app/auth/auth.service.ts:16:31)
            at node_modules/@angular/core/fesm5/core.js:15518:29
            at _callFactory (node_modules/@angular/core/fesm5/core.js:21279:1)
            at _createProviderInstance (node_modules/@angular/core/fesm5/core.js:21237:1)
            at resolveNgModuleDep (node_modules/@angular/core/fesm5/core.js:21212:1)
            at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (node_modules/@angular/core/fesm5/core.js:21906:1)
            at TestBedViewEngine.push../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.get (node_modules/@angular/core/fesm5/testing.js:1815:1)
            at Function.push../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.get (node_modules/@angular/core/fesm5/testing.js:1598:1)
            at UserContext.<anonymous> (src/app/auth/auth.service.spec.ts:37:42)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:391:1)

我的理解是,这是因为我的authState无法观察到,但是这开始变得很麻烦。应该怎么做?

1 个答案:

答案 0 :(得分:0)

可能是因为TestStore是错的吗?请改用NgRx MockStore

TestBed.configureTestingModule({
      imports: [
        // any modules needed
      ],
      providers: [
        provideMockStore({ initialState }),
        // other providers
      ],
});