我正在使用Angular6,并且试图使我的Jasmine测试到达mergeMap波纹管内部的回调,但是经过几天的工作,我却无能为力。
我的测试正确返回了刷新方法,但似乎并没有通过管道。
这是我要测试的完整方法:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (
this.jwtInterceptor.isWhitelistedDomain(req) &&
!this.jwtInterceptor.isBlacklistedRoute(req)
) {
const newRequest = req.clone();
return next.handle(newRequest).pipe(
tap(() => {
const token = this.jwtHelper.tokenGetter();
if (token) {
const expirationTime = this.jwtHelper
.getTokenExpirationDate()
.getTime();
const expirationLeft = expirationTime - Date.now();
const expired =
expirationLeft > 0 && expirationLeft < 5 * 60 * 1000;
if (expired && !this.isUpdating) {
this.isUpdating = true;
return this.refresh().pipe(
mergeMap(() => { // this is the unreachable part
return this.jwtInterceptor.intercept(req, next);
})
);
}
}
}),
catchError(err => {
if (err instanceof HttpErrorResponse && err.status === 401) {
this.router.navigate([this.config.routeToGoIfNotLoggedIn]);
}
return throwError(err);
})
);
} else {
return next.handle(req);
}
}
这里返回了我的this.refresh()方法:
refresh(): Observable<any> {
const refreshObservable = this.authAPI.refreshToken();
const refreshSubject = new ReplaySubject<any>(1);
refreshSubject.subscribe(
data => {
localStorage.setItem('token', data.jwt);
this.isUpdating = false;
},
err => {
this.isUpdating = false;
this.userLoggedService.removeUserLoggedAndToken();
}
);
refreshObservable.subscribe(refreshSubject);
return refreshSubject;
}
}
这是我在refresh()内部触发的this.authAPI.refreshToken():
refreshToken() {
return this.http.get(`${this.config.baseAPIUrl}refreshToken`);
}
在我的httpTestingController中正确捕获了http调用,最终的期望是触发了this.jwtInterceptor.intercept(req,next)。
这是我失败的那部分的规格:
it('should call Refresh method if token is expiring in 5 minutes', () => {
const nowInMillisec = Number(new Date());
const FourMinutesFromNow = nowInMillisec + 4 * 60000;
spyOn(
jwtService,
'getTokenExpirationDate'
).and.returnValue(new Date(FourMinutesFromNow));
const jwtInterceptor = TestBed.get(JwtInterceptor);
const spyOnJwtInterceptor = spyOn(jwtInterceptor, 'intercept');
dummyService.fakeHttpCall().subscribe();
httpTestingController.expectOne(
`${MockAuthConfig.baseAPIUrl}user/fake-call`
);
const callbackHttpFired = httpTestingController.expectOne(
`${MockAuthConfig.baseAPIUrl}refreshToken`
);
expect(callbackHttpFired.request.url).toEqual(
`${MockAuthConfig.baseAPIUrl}refreshToken`
);
expect(spyOnJwtInterceptor).toHaveBeenCalled(); // this spy is never fired... :(
});
有什么想法吗? 非常感谢你!
答案 0 :(得分:1)
这里done()
的使用至关重要,因为subscribe
的调用是异步的,其余测试在subscribe
退出之前运行。另外,您应该分别测试refresh
方法。首次测试refresh
intercept
然后应使用
更改签名。it('should call Refresh method if token is expiring in 5 minutes', (done) => {
...
jwtInterceptor.intecept.subscribe(() => {
expect(spyOnJwtInterceptor).toHaveBeenCalled();
done();
});
}
因此,测试方法将等待,直到调用done()。期望会按计划进行。