如何使用注入的对象测试角度http拦截器

时间:2018-02-06 07:49:55

标签: angular typescript jasmine

我正在尝试测试我的拦截器是否会向ngrx商店发送正确的操作,如果后端响应419状态代码 - 我们用它来表示用户会话已到期。

如果我手动尝试它是有效的 - 但我无法通过单元测试来验证这一点。对我店的打电话从未发生过。我认为我监视的商店不是注入拦截器的商店,或者我希望以某种方式提前通知?

到目前为止,这是我的代码:

fdescribe('Http Session Timeout Interceptor', () => {
    let store: Store<AppState>;

    beforeEach(() => {

        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule, StoreModule.forRoot(appReducers)],
            providers: [{
                provide: HTTP_INTERCEPTORS,
                useClass: HttpSessionTimeoutInterceptor,
                multi: true
            }]
        });
        store = TestBed.get(Store);
        spyOn(store, 'dispatch');
    });

    it('interceptor is called',
        inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
        http.get('/api').subscribe(response => {
           const cast = response as HttpResponse<String>;
           expect(cast.status).toBe(419);
        });
        const req = httpMock.expectOne('/api');
        req.flush(<HttpResponse<String>>{status: 419});
        httpMock.verify();
        expect(store.dispatch).toHaveBeenCalledWith(new SessionTimeOutAction());
        }));
});

这是拦截器,只需检查响应状态并调度操作:

@Injectable()
export class HttpSessionTimeoutInterceptor implements HttpInterceptor {
    constructor(private store: Store<AppState>) {}

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req)
            .catch(response => {
                if (response.status === 419) {
                    this.store.dispatch(new SessionTimeOutAction());
                }
                return Observable.throw(response);
            }) as any;
    }
}

1 个答案:

答案 0 :(得分:0)

我认为您需要在提供者中提供Store<AppState>依赖性。不像HTTP_INTERCEPTORS那样作为JSON,而是作为provider数组中的简单条目。当然也要删除顶部的声明。您可以将TestBed视为用于测试的NgModule。因此,要找到要注入的依赖项,Angular会对其进行扫描以查找所需的令牌。不幸的是,如果您没有这样做,大多数情况下您不会得到有用的错误。