0

在为我们在 Angular 应用程序中编写的 auth 保护实现 Spec 文件时,给了我一个错误,我无法考虑正在发生的事情。

Auth Guard -------------> should return FALSE if the user state is not logged in FAILED
        TypeError: actual.subscribe is not a function
            at VirtualAction.<anonymous> (node_modules/jasmine-marbles/es6/index.js:55:1)
            at VirtualAction._execute (node_modules/rxjs/_esm2015/internal/scheduler/AsyncAction.js:51:1)
            at VirtualAction._execute (node_modules/rxjs/_esm2015/internal/scheduler/VirtualTimeScheduler.js:59:1)
            at VirtualAction.execute (node_modules/rxjs/_esm2015/internal/scheduler/AsyncAction.js:39:1)
            at TestScheduler.flush (node_modules/rxjs/_esm2015/internal/scheduler/VirtualTimeScheduler.js:16:1)
            at TestScheduler.flush (node_modules/rxjs/_esm2015/internal/testing/TestScheduler.js:107:1)
            at toBeObservableComparer (node_modules/jasmine-marbles/es6/index.js:77:1)
            at <Jasmine>
            at UserContext.<anonymous> (src/app/core/guards/auth.guard.spec.ts:55:37)

以上是我在为 auth.guard.spec.ts 和 auth.guard.ts 粘贴以下代码时面临的问题

import { TestBed } from '@angular/core/testing';
import { combineReducers, Store, StoreModule } from '@ngrx/store';
import { cold } from 'jasmine-marbles';
import { addMatchers, initTestScheduler } from 'jasmine-marbles';
import { RouterTestingModule } from '@angular/router/testing';
import { provideMockStore } from '@ngrx/store/testing';

import { AuthGuard } from './auth.guard';
import * as fromRoot from '../../app-state';
import * as fromAuth from '../../modules/auth/store/auth.reducer';
import * as fromAuthActions from '../../modules/auth/store/auth.actions';
import { User } from '../../modules/auth/login/login.model';
import { LogInComponent } from '../../modules/auth/login/login.component';

describe('Auth Guard', () => {
    let guard: AuthGuard;
    let store: Store<any>;
    const initialState = { loggedIn: false };
    beforeEach(() => {
        initTestScheduler();
        addMatchers();
        TestBed.configureTestingModule({
            imports: [
                RouterTestingModule.withRoutes([
                    { path: 'auth', component: LogInComponent }
                ]),
                StoreModule.forRoot({
                    ...fromRoot.reducers,
                    auth: combineReducers(fromAuth.reducer)
                })
            ],
            providers: [
                AuthGuard,
                provideMockStore({ initialState })
            ]
        });
        store = TestBed.inject(Store);
        spyOn(store, 'dispatch').and.callThrough();
        guard = TestBed.inject(AuthGuard);
    });

    it('-------------> should return FALSE if the user state is not logged in', () => {
        const expected = cold('(a|)', { a: false });
        expect(guard.canActivate()).toBeObservable(expected);
    });
});

守卫.ts

import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';
import { AppState } from 'src/app/app-state';
import * as fromAuth from '../../modules/auth/store/auth.reducer';

@Injectable()
export class AuthGuard implements CanActivate {
  authState: Observable<fromAuth.AuthState>;
  constructor(private store: Store<AppState>, private router: Router) { }
  canActivate(): boolean {
    // Check if user is authenticated or not i.e. only logged in users havce access to todos page
    const authState = this.store.select(fromAuth.selectAuthState);
    authState.subscribe(state => {
      if (!state.isAuthenticated) {
        this.router.navigate(['auth']);
        return false;
      }
    });

    return true;
  }
}
4

1 回答 1

0

我认为由于您canActivate返回的是 aboolean而不是 a Observable<boolean>,因此这可能是问题所在。

尝试改变你的canActivate喜欢:

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
....
canActivate(): Observable<boolean> {
    // Check if user is authenticated or not i.e. only logged in users have access to todos page
    return this.store.select(fromAuth.selectAuthState).pipe(
      map(state => {
        if (!state.isAuthenticated) {
          this.router.navigate(['auth']);
          return false;
        }
        return true;
      }),
    );
  }

现在,我们将返回一个 observable,然后在您的测试中expect(guard.canActivate()).toBeObservable(...)应该可以工作。之前guard.canActivate()是 aboolean而不是Observable.

于 2021-10-04T15:23:54.193 回答