我有一个拦截器,如果任何响应包含401,它会自动将用户注销。
// error.interceptor.ts
import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {AuthService} from 'angularx-social-login';
import {CookieService} from 'ngx-cookie';
import {Router} from '@angular/router';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
user: any;
constructor(
private router: Router,
private authService: AuthService,
private cookieService: CookieService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.user = this.cookieService.getObject('user');
return next.handle(request).pipe(catchError(err => {
if (err.status === 401) {
// auto logout if 401 response returned from api
this.cookieService.remove('user');
this.cookieService.remove('google');
this.authService.signOut();
location.reload(true);
}
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
}
我的茉莉花测试看起来像这样。除了被拦截的服务(在这种情况下为UserService
之外,我已经嘲笑了所有内容。
// error.interceptor.spec.ts
import { CookieService } from "ngx-cookie";
import { Router } from "@angular/router";
import { AuthService, SocialUser } from "angularx-social-login";
import { UserService } from "../services/user/user.service";
import { TestBed, inject } from "@angular/core/testing";
import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
import { HTTP_INTERCEPTORS, HttpClient } from "@angular/common/http";
import { ErrorInterceptor } from "./error.interceptor";
import { environment } from "../../environments/environment";
describe('ErrorInterceptor', () => {
let cookieServiceMock: jasmine.SpyObj<CookieService>;
let routerMock: jasmine.SpyObj<Router>;
let authServiceMock: jasmine.SpyObj<AuthService>
let service: UserService;
const cookie = {
google: {
'userName': 'john.doe'
},
user: {
'userName': 'john.doe'
}
};
beforeEach(() => {
routerMock = jasmine.createSpyObj<Router>('Router', ['navigate']);
authServiceMock = jasmine.createSpyObj<AuthService>('AuthService', ['signOut']);
cookieServiceMock = jasmine.createSpyObj<CookieService>('CookieService', ['remove', 'putObject', 'getObject']);
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true},
{provide: Router, useValue: routerMock},
{provide: AuthService, useValue: authServiceMock},
{provide: CookieService, useValue: cookieServiceMock},
{provide: SocialUser, useValue: cookie.google},
UserService
]
})
});
afterEach(inject(
[HttpTestingController],
(httpMock: HttpTestingController) => {
httpMock.verify();
}
));
fit('returns an error if request is invalid',
inject(
[HttpClient, HttpTestingController, UserService, HTTP_INTERCEPTORS],
(http: HttpClient, httpMock: HttpTestingController, service: UserService) => {
cookieServiceMock.getObject.and.returnValue(cookie.user);
service.getUserList().subscribe(
data => console.log(data),
err => expect(err).toBe('Unauthorized')
);
// localhost:8080/v1/api/user
const req = httpMock.expectOne(environment.coreUrl + environment.basePath + '/user');
expect(req.request.method).toBe('GET');
// mocks a response containing a 401 code
req.flush('Unauthorized', {statusText: 'Unauthorized', status: 401});
}
)
);
});
请注意,上面的测试用例使用fit
,因此只有在执行ng test
时才运行该测试。当我运行测试时,它并没有结束。终端输出如下:
HeadlessChrome 0.0.0 (Linux 0.0.0): Executed 1 of 182 SUCCESS (0 secs / 0.124 secs)
HeadlessChrome 0.0.0 (Linux 0.0.0): Executed 2 of 182 (skipped 4) SUCCESS (0 secs / 0.161 secs)
HeadlessChrome 0.0.0 (Linux 0.0.0): Executed 3 of 182 (skipped 8) SUCCESS (0 secs / 0.182 secs)
...
发生了什么事?以及如何解决?