[英]spyOn not working in Http Interceptor in Angular 6
I am trying to test HttpInterceptor that logs the response of the http
request.我正在尝试测试记录
http
请求响应的 HttpInterceptor。 I have a log service that logs the response of the request.我有一个记录请求响应的日志服务。 The interceptor logs only for GET requeststs.
拦截器只记录 GET 请求。
Here's my interceptor:这是我的拦截器:
import { HttpInterceptor, HttpHandler, HttpEvent, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { LogService } from './log.service';
import { Injectable } from '@angular/core';
@Injectable({providedIn: 'root'})
export class LoggerInterceptor implements HttpInterceptor {
constructor(private _log: LogService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
tap(event => {
if (event instanceof HttpResponse) {
if (req.method === 'GET') {
this._log.log('I was logged');
}
}
})
);
}
}
Here's the spec file:这是规范文件:
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { HeaderInterceptor } from './add.header.interceptor';
import { LogService } from './log.service';
import { LoggerInterceptor } from './logger.interceptor';
const posts: Array<any> = [
{
'userId': 1,
'id': 1,
'title': 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
'body': 'quia et suscipit\nsuscipit recusandae consequuntur expedita et '
},
{
'userId': 1,
'id': 2,
'title': 'qui est esse',
'body': 'est rerum tempore vitae\nsequi sint nihil reprehenderit dolor b'
}
];
describe('HeaderInterceptor', () => {
let httpMock: HttpTestingController;
let logService: LogService;
let httpClient: HttpClient;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule ],
providers: [
LogService,
{ provide: HTTP_INTERCEPTORS, useClass: LoggerInterceptor, multi: true }
]
});
httpMock = TestBed.get(HttpTestingController);
logService = TestBed.get(LogService);
httpClient = TestBed.get(HttpClient);
});
it('must log the http get request', () => {
const spy = spyOn(logService, 'log');
httpClient.get('http://jsonplaceholder.typicode.com/posts')
.subscribe(
(data: Array<any>) => {
expect(data.length).toBe(2);
}
);
const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
expect(req.request.headers.has('Content-Type')).toBe(true);
expect(spy).toHaveBeenCalled();
req.flush(posts);
});
it('must log the http post request', () => {
const spy = spyOn(logService, 'log');
httpClient.post('http://jsonplaceholder.typicode.com/posts', posts)
.subscribe();
const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
expect(req.request.headers.has('Content-Type')).toBe(true);
expect(spy).not.toHaveBeenCalled();
req.flush(posts);
});
});
I have HeaderInterceptor that adds Content-Type
header to each http request.我有 HeaderInterceptor 为每个 http 请求添加
Content-Type
标头。 Testing of that interceptor works fine.该拦截器的测试工作正常。
When I tried to test the LoggerInterceptor, I get error on the spy expect(spy).toHaveBeenCalled();
当我尝试测试 LoggerInterceptor 时,我在 spy
expect(spy).toHaveBeenCalled();
上收到错误expect(spy).toHaveBeenCalled();
Here's the error:这是错误:
Error: Expected spy log to have been called.
at stack (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2455:17)
at buildExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2425:14)
at Spec.expectationResultFactory (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:901:18)
at Spec.addExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:524:34)
at Expectation.addExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:845:21)
at Expectation.toHaveBeenCalled (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2369:12)
at UserContext.<anonymous> (http://localhost:9876/src/app/logger.interceptor.spec.ts?:57:17)
at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:388:1)
at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:288:1)
at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:387:1)
Not really sure where I am going wrong.不太确定我哪里出错了。 I am executing the post http call for the sake of code-coverage.
为了代码覆盖,我正在执行 post http 调用。 What do I need to fix?
我需要修复什么?
This might only be a partial answer.这可能只是部分答案。
I am not expert in testing, so I shouldn't try to explain why your code failing, but I believe the code below is correct and doing true tests.我在测试中没有专家,所以我不应该试图解释为什么你的代码失败了,但我相信下面的代码是正确的,做真正的测试。
IMO there are two problems in your code in the GET case: - you are flushing after expecting the spy - should be the other way around - you are not calling done()
from within .subscribe()
IMO 在 GET 情况下,您的代码中有两个问题: - 您在期待间谍之后正在冲洗 - 应该是相反的 - 您没有从
.subscribe()
调用done()
.subscribe()
Your code for POST case seems to work ok though (except that the test description seems incorrect, shouldn't it be "should NOT log" instead?)不过,您的 POST 案例代码似乎可以正常工作(除了测试描述似乎不正确,难道不应该改为“不应该记录”吗?)
I have left out the check of Content-Type
header as it was failing for some reason (don't have time to investigate it further - will be curious to see if you solve it) and it was not part of your question.我省略了对
Content-Type
标头的检查,因为它由于某种原因失败了(没有时间进一步调查 - 很想知道您是否解决了它)并且它不是您问题的一部分。
describe('Logger Interceptor', () => {
let httpMock: HttpTestingController;
let httpClient: HttpClient;
let logService: LogService;
let spy: Function;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: LoggerInterceptor,
multi: true,
},
],
});
httpClient = TestBed.get(HttpClient);
httpMock = TestBed.get(HttpTestingController);
logService = TestBed.get(LogService);
spy = spyOn(logService, 'log');
});
afterEach(() => httpMock.verify());
it('must log the http get request', (done) => {
httpClient.get('http://jsonplaceholder.typicode.com/posts').subscribe((data: any[]) => {
expect(data.length).toBe(2);
done();
});
const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
req.flush(posts);
expect(spy).toHaveBeenCalled();
});
it('should NOT log the http post request', () => {
httpClient.post('http://jsonplaceholder.typicode.com/posts', posts)
.subscribe();
const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
expect(spy).not.toHaveBeenCalled();
req.flush(posts);
});
});
I would be curious to hear why the GET case requires the above changes, should anyone be able to explain.如果有人能够解释,我很想知道为什么 GET 案例需要进行上述更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.