Я пишу приложение с использованием NativeScript 6.4.1 и Angular 8.
Я хочу написать модульные тесты для моего HttpInterceptor. Мой перехватчик добавляет токен для выбора 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);
}
}