具有自定义 header 的单元测试拦截器
Unit testing interceptor with custom header
我一直在尝试 运行 拦截器中的测试单元 Angular 6,但是经过多次试验和错误后,我不断收到以下错误:
Error: Expected one matching request for criteria "Match by function: ", found none.
我对 NG6 及其单元测试有点陌生,在文档中找不到任何内容
这是我得到的:
Token Service(与后台无关联所以被嘲笑)
export class TokenService {
token: EventEmitter<any> = new EventEmitter();
findTokenData(): Observable<any> {
return Observable.create((observer: Observer<object>) => {
observer.next({ headerName: x-fake, token: fake' });
observer.complete();
});
}
}
休息拦截器
export class RestInterceptor implements HttpInterceptor {
constructor(public tokenService: TokenService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('request intercepted...');
let authReq: HttpRequest<any>;
const customHeadersMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];
// If the requested method is different GET or HEAD request the CSRF token from the service and add it to the headers
if (customHeadersMethods.indexOf(req.method) !== -1) {
this.tokenService.findTokenData().subscribe(res => {
authReq = req.clone({
headers: req.headers.set(res.headerName, res.token),
});
});
} else {
authReq = req.clone();
}
// send the newly created request
return next.handle(authReq);
}
}
rest 拦截器规范
describe('RestInterceptor', () => {
const mockTokenService = {
headerName: 'x-fake',
token: 'fake'
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: TokenService,
useValue: mockTokenService
},
{
provide: HTTP_INTERCEPTORS,
useClass: RestInterceptor,
multi: true
}]
});
});
afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
httpMock.verify();
}));
it('Should add a custom header', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
http.post('/data', {}).subscribe(
response => {
expect(response).toBeTruthy();
}
);
const req = httpMock.expectOne(r =>
r.headers.has(`${mockTokenService.headerName}`) &&
r.headers.get(`${mockTokenService.headerName}`) === `${mockTokenService.token}`);
expect(req.request.method).toEqual('POST');
httpMock.verify();
}));
});
任何人都可以帮助我了解我缺少什么吗?
我想你错过了一个事实,即 TokenService
不是简单的值,而是 class 和 returns 可观察的 findTokenData
方法。
事情是这样的:
您定义了 mock:
const mockTokenService = {
headerName: 'x-fake',
token: 'fake'
};
覆盖它:
{
provide: TokenService,
useValue: mockTokenService
},
现在 Angular 将使用此 mockTokenService
对象作为注入 RestInterceptor
和...
的值
this.tokenService.findTokenData().subscribe(res => {
||
undefined => error
所以您可以采取以下措施来解决这个问题:
import { of } from 'rxjs';
...
const mockToken = {
headerName: 'x-fake',
token: 'fake'
};
const mockTokenService = {
findTokenData: () => {
return of(mockToken);
}
};
...
const req = httpMock.expectOne(r =>
r.headers.has(`${mockToken.headerName}`) &&
r.headers.get(`${mockToken.headerName}`) === `${mockToken.token}`);
我一直在尝试 运行 拦截器中的测试单元 Angular 6,但是经过多次试验和错误后,我不断收到以下错误:
Error: Expected one matching request for criteria "Match by function: ", found none.
我对 NG6 及其单元测试有点陌生,在文档中找不到任何内容
这是我得到的:
Token Service(与后台无关联所以被嘲笑)
export class TokenService {
token: EventEmitter<any> = new EventEmitter();
findTokenData(): Observable<any> {
return Observable.create((observer: Observer<object>) => {
observer.next({ headerName: x-fake, token: fake' });
observer.complete();
});
}
}
休息拦截器
export class RestInterceptor implements HttpInterceptor {
constructor(public tokenService: TokenService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('request intercepted...');
let authReq: HttpRequest<any>;
const customHeadersMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];
// If the requested method is different GET or HEAD request the CSRF token from the service and add it to the headers
if (customHeadersMethods.indexOf(req.method) !== -1) {
this.tokenService.findTokenData().subscribe(res => {
authReq = req.clone({
headers: req.headers.set(res.headerName, res.token),
});
});
} else {
authReq = req.clone();
}
// send the newly created request
return next.handle(authReq);
}
}
rest 拦截器规范
describe('RestInterceptor', () => {
const mockTokenService = {
headerName: 'x-fake',
token: 'fake'
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: TokenService,
useValue: mockTokenService
},
{
provide: HTTP_INTERCEPTORS,
useClass: RestInterceptor,
multi: true
}]
});
});
afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
httpMock.verify();
}));
it('Should add a custom header', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
http.post('/data', {}).subscribe(
response => {
expect(response).toBeTruthy();
}
);
const req = httpMock.expectOne(r =>
r.headers.has(`${mockTokenService.headerName}`) &&
r.headers.get(`${mockTokenService.headerName}`) === `${mockTokenService.token}`);
expect(req.request.method).toEqual('POST');
httpMock.verify();
}));
});
任何人都可以帮助我了解我缺少什么吗?
我想你错过了一个事实,即 TokenService
不是简单的值,而是 class 和 returns 可观察的 findTokenData
方法。
事情是这样的:
您定义了 mock:
const mockTokenService = {
headerName: 'x-fake',
token: 'fake'
};
覆盖它:
{
provide: TokenService,
useValue: mockTokenService
},
现在 Angular 将使用此 mockTokenService
对象作为注入 RestInterceptor
和...
this.tokenService.findTokenData().subscribe(res => {
||
undefined => error
所以您可以采取以下措施来解决这个问题:
import { of } from 'rxjs';
...
const mockToken = {
headerName: 'x-fake',
token: 'fake'
};
const mockTokenService = {
findTokenData: () => {
return of(mockToken);
}
};
...
const req = httpMock.expectOne(r =>
r.headers.has(`${mockToken.headerName}`) &&
r.headers.get(`${mockToken.headerName}`) === `${mockToken.token}`);