带有 delay() 的 Jasmine Karma 测试函数

Jasmine Karma testing function with delay()

我有一个 angular class 像这样 (angular 8)

@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private loginService: LoginService) { }

  private  authenticated = false;
  private  retry = 0;
 
  canActivate(route: ActivatedRouteSnapshot,router: RouterStateSnapshot): Observable<boolean> | boolean {

    if (this.authenticated) {
      return true;
    }

    return of(null).pipe(
        delay(this.retry++ >0 ? 5000 : 0), //start delay on second retry for debouncing request
        flatMap(() =>
           this.loginService.isLoggedIn().pipe(
            map(result => {
              this.authenticated = result;
              return this.authenticated;
            }))
        )
      );
  }

}

我正在尝试如下进行测试:

describe('AuthGuard', () => {

  let service: LoginService;
  let guard: AuthGuard;
  let router: Router;
//left out other irrelevant fields here
  
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule, RouterTestingModule],
      providers: [LoginService]
    });
    router = TestBed.inject(Router);
    service = TestBed.inject(LoginService);
    http = TestBed.inject(HttpClient);
    httpClientMock = TestBed.inject(HttpTestingController);
    guard = TestBed.inject(AuthGuard);
  });

  it('should return false for canActivate() if user is not logged in',()=> {
    spyOn(service, 'isLoggedIn').and.returnValue(of(false));

    const result = guard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});

    if (isObservable(result)) {
      console.log("observable!")
      result.subscribe(
        res => {
          console.log("res is " + res)
          expect(res).toBeFalsy("Did not get FALSE for user that is not logged in")
        })
    }
  });

我还有另一个相同的用户登录测试 - (isLoggedIn = true) 然而,似乎(可能是因为延迟)订阅函数没有被调用。我看到日志“可观察!”但不是“res is {res}”。我尝试使用 fakeAsync 和各种东西,但没有任何效果。

非常感谢您的帮助!谢谢

(如果我在原始函数中注释掉“延迟”,则测试运行良好) 同样,我没有更改原始 canActivate 函数的选项

试试这个:

it('should return false for canActivate() if user is not logged in', fakeAsync(()=> {
    spyOn(service, 'isLoggedIn').and.returnValue(of(false));

    const result = guard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});

    if (isObservable(result)) {
      console.log("observable!");
      let result; // get a variable here to assign to result
      const subscription = result.subscribe(
        res => {
          console.log("res is " + res)
          expect(res).toBeFalsy("Did not get FALSE for user that is not logged in")
          result = res; // assign to result
        });
      tick(5000);
      expect(result).toBe(false);
      subscription.unsubscribe(); // unsubscribe from the subscription
    }
  }));

检查此 link