NativeScript - 单元测试 HttpInterceptor NSLocationStrategy 错误
NativeScript - unit testing an HttpInterceptor NSLocationStrategy error
我正在使用 NativeScript 6.4.1 和 Angular 8 编写应用程序。
我想为我的 HttpInterceptor 编写单元测试。我的拦截器将令牌添加到 select http 调用,如果用户从后端收到某些错误,则将用户路由到身份验证页面。
代码 运行 没问题,它可以工作,但我的单元测试没有。
当我 运行 我的单元测试时,我得到这个错误:
NullInjectorError: StaticInjectorError(DynamicTestModule)[RouterExtensions -> NSLocationStrategy]:
StaticInjectorError(Platform: core)[RouterExtensions -> NSLocationStrategy]:
NullInjectorError: No provider for NSLocationStrategy!
error properties: Object({ originalStack: 'Error: NullInjectorError: No provider for NSLocationStrategy!
at new ZoneAwareError (file:///data/data/org.nativescript.SelfServiceApp/files/app/vendor.js:157861:33)
我不知道为什么会收到错误消息。
这是我的单元测试:
import { nsTestBedBeforeEach } from 'nativescript-angular/testing';
import { TestBed } from '@angular/core/testing';
import { HttpInterceptorService } from '~/app/core/interceptors/http-interceptor-service';
import { HttpLoaderService } from '~/app/core/shared/http-loader.service';
import { AuthenticationService } from '~/app/authentication/shared/services/authentication.service';
import { SsoAuthenticationService } from '~/app/authentication/pages/single-sign-on/sso-authentication.service';
import { EndpointHelperService } from '~/app/core/shared/endpoint-helper.service';
import { RouterExtensions } from 'nativescript-angular/router';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NativeScriptRouterModule } from 'nativescript-angular/router';
import { Routes, RouterModule } from '@angular/router';
import { CommonModule, Location } from '@angular/common';
describe('HttpInterceptorService Test', () => {
let service: HttpInterceptorService;
beforeEach(nsTestBedBeforeEach([], [
HttpInterceptorService,
HttpLoaderService,
AuthenticationService,
SsoAuthenticationService,
EndpointHelperService,
RouterExtensions
], [
HttpClientTestingModule,
RouterTestingModule,
NativeScriptRouterModule,
CommonModule
]));
it('should be defined', () => {
service = TestBed.get(HttpInterceptorService);
expect(service).toBeTruthy();
});
});
这是我的拦截器:
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError, from } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { HttpLoaderService } from '../shared/http-loader.service';
import { boundMethod } from 'autobind-decorator';
import { AuthenticationService } from '../../authentication/shared/services/authentication.service';
import { SsoAuthenticationService } from '../../authentication/pages/single-sign-on/sso-authentication.service';
import { EndpointHelperService } from '../shared/endpoint-helper.service';
import { switchMap } from 'rxjs/operators';
import { RouterExtensions } from 'nativescript-angular/router';
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
constructor(
private httpLoaderService: HttpLoaderService,
private authentication: AuthenticationService,
private ssoAuthentication: SsoAuthenticationService,
private endpointHelper: EndpointHelperService,
private router: RouterExtensions
) {}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.httpLoaderService.onRequestStart();
// do not add to token endpoints
if (this.endpointHelper.isTokenEndpoint(request.url)) {
return this.returnRequest(request, next);
}
//do not add to registration server
if (this.endpointHelper.isRegisterEndpoint(request.url)) {
return this.returnRequest(request, next);
}
return this.appendSSOTokenToHeader(request, next);
}
@boundMethod
private appendSSOTokenToHeader(request: HttpRequest<any>, next: HttpHandler) {
return from(this.ssoAuthentication.getHttpHeader())
.pipe(
switchMap((newHeader) => {
request = request.clone({
body: { ...request.body, clientcode: this.authentication.clientcode },
setHeaders: { Authorization: newHeader },
url: this.authentication.mobileApiUrl + request.url
});
return this.returnRequest(request, next);
})
);
}
@boundMethod
private returnRequest(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next
.handle(request)
.pipe(tap(this.handleSuccess), catchError(this.handleError));
}
@boundMethod
private handleSuccess(event: HttpEvent<any>): void {
if (event instanceof HttpResponse) {
this.httpLoaderService.onRequestEnd();
}
}
@boundMethod
private handleError(error: HttpErrorResponse) {
this.httpLoaderService.onRequestEnd();
if (this.endpointHelper.shouldRedirectToSSOPage(error)) {
this.router.navigate(['register-via-sso']);
}
return throwError(error);
}
}
您必须将 NativeScriptRouterModule
加载为 NativeScriptRouterModule.forRoot([])
,这类似于在您的应用程序模块中加载具有可用路由的路由器。既然是单元测试,这里就不要传入routes了。
我正在使用 NativeScript 6.4.1 和 Angular 8 编写应用程序。
我想为我的 HttpInterceptor 编写单元测试。我的拦截器将令牌添加到 select http 调用,如果用户从后端收到某些错误,则将用户路由到身份验证页面。
代码 运行 没问题,它可以工作,但我的单元测试没有。
当我 运行 我的单元测试时,我得到这个错误:
NullInjectorError: StaticInjectorError(DynamicTestModule)[RouterExtensions -> NSLocationStrategy]:
StaticInjectorError(Platform: core)[RouterExtensions -> NSLocationStrategy]:
NullInjectorError: No provider for NSLocationStrategy!
error properties: Object({ originalStack: 'Error: NullInjectorError: No provider for NSLocationStrategy!
at new ZoneAwareError (file:///data/data/org.nativescript.SelfServiceApp/files/app/vendor.js:157861:33)
我不知道为什么会收到错误消息。
这是我的单元测试:
import { nsTestBedBeforeEach } from 'nativescript-angular/testing';
import { TestBed } from '@angular/core/testing';
import { HttpInterceptorService } from '~/app/core/interceptors/http-interceptor-service';
import { HttpLoaderService } from '~/app/core/shared/http-loader.service';
import { AuthenticationService } from '~/app/authentication/shared/services/authentication.service';
import { SsoAuthenticationService } from '~/app/authentication/pages/single-sign-on/sso-authentication.service';
import { EndpointHelperService } from '~/app/core/shared/endpoint-helper.service';
import { RouterExtensions } from 'nativescript-angular/router';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NativeScriptRouterModule } from 'nativescript-angular/router';
import { Routes, RouterModule } from '@angular/router';
import { CommonModule, Location } from '@angular/common';
describe('HttpInterceptorService Test', () => {
let service: HttpInterceptorService;
beforeEach(nsTestBedBeforeEach([], [
HttpInterceptorService,
HttpLoaderService,
AuthenticationService,
SsoAuthenticationService,
EndpointHelperService,
RouterExtensions
], [
HttpClientTestingModule,
RouterTestingModule,
NativeScriptRouterModule,
CommonModule
]));
it('should be defined', () => {
service = TestBed.get(HttpInterceptorService);
expect(service).toBeTruthy();
});
});
这是我的拦截器:
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError, from } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { HttpLoaderService } from '../shared/http-loader.service';
import { boundMethod } from 'autobind-decorator';
import { AuthenticationService } from '../../authentication/shared/services/authentication.service';
import { SsoAuthenticationService } from '../../authentication/pages/single-sign-on/sso-authentication.service';
import { EndpointHelperService } from '../shared/endpoint-helper.service';
import { switchMap } from 'rxjs/operators';
import { RouterExtensions } from 'nativescript-angular/router';
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
constructor(
private httpLoaderService: HttpLoaderService,
private authentication: AuthenticationService,
private ssoAuthentication: SsoAuthenticationService,
private endpointHelper: EndpointHelperService,
private router: RouterExtensions
) {}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.httpLoaderService.onRequestStart();
// do not add to token endpoints
if (this.endpointHelper.isTokenEndpoint(request.url)) {
return this.returnRequest(request, next);
}
//do not add to registration server
if (this.endpointHelper.isRegisterEndpoint(request.url)) {
return this.returnRequest(request, next);
}
return this.appendSSOTokenToHeader(request, next);
}
@boundMethod
private appendSSOTokenToHeader(request: HttpRequest<any>, next: HttpHandler) {
return from(this.ssoAuthentication.getHttpHeader())
.pipe(
switchMap((newHeader) => {
request = request.clone({
body: { ...request.body, clientcode: this.authentication.clientcode },
setHeaders: { Authorization: newHeader },
url: this.authentication.mobileApiUrl + request.url
});
return this.returnRequest(request, next);
})
);
}
@boundMethod
private returnRequest(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next
.handle(request)
.pipe(tap(this.handleSuccess), catchError(this.handleError));
}
@boundMethod
private handleSuccess(event: HttpEvent<any>): void {
if (event instanceof HttpResponse) {
this.httpLoaderService.onRequestEnd();
}
}
@boundMethod
private handleError(error: HttpErrorResponse) {
this.httpLoaderService.onRequestEnd();
if (this.endpointHelper.shouldRedirectToSSOPage(error)) {
this.router.navigate(['register-via-sso']);
}
return throwError(error);
}
}
您必须将 NativeScriptRouterModule
加载为 NativeScriptRouterModule.forRoot([])
,这类似于在您的应用程序模块中加载具有可用路由的路由器。既然是单元测试,这里就不要传入routes了。