Jim*_*Jim 5 testing dependency-injection jasmine angular
我目前正在构建一个Angular2应用程序,我正在编写测试,但是我遇到了一个在创建测试模块时似乎无法解决的问题.
我创建了一个自定义类,它扩展了Angular2 HTTP模块并用作拦截器.该类负责身份验证逻辑和其他类似的事情.
这是HttpInterceptor类.这用来代替Angular2 HTTP核心类,它只是它的扩展:
import { Injectable, Inject } from "@angular/core";
import { Http, ConnectionBackend, RequestOptions, Request, RequestOptionsArgs, Response } from "@angular/http";
import { Observable } from "rxjs";
import { AuthService } from "./auth.service";
import { GlobalEventsManager } from "./globalEventsManager.service";
import { messages } from "../helpers/messages";
@Injectable()
export class HttpInterceptor extends Http {
constructor(
backend: ConnectionBackend,
defaultOptions: RequestOptions,
public _authService: AuthService,
public _globalEventsManager: GlobalEventsManager
) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return super.request(url, options).catch(res => {
if(res.statusCode === 401) {
console.log('expired');
}
});
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
var obsStream = super.request(url, options);
obsStream.subscribe((data) => {
var JSONParsedRes = JSON.parse(data._body);
if(JSONParsedRes.statusCode) {
if(JSONParsedRes.statusCode == 401) {
this._globalEventsManager.showNavBar.emit(false);
this._authService.logout({message: messages.messages.auth.tokenExpired, title:messages.titles.auth.tokenExpired});
}
}
});
return obsStream;
}
handleError() {
console.log('error');
}
}
Run Code Online (Sandbox Code Playgroud)
这是我试图测试的服务:
import { Injectable, EventEmitter } from "@angular/core";
import { RequestOptions } from "@angular/http";
import { Product } from "../classes/Product";
import { Observable } from "rxjs";
import { routes } from "../routes";
import { StringHelper } from "../helpers/StringHelper";
import { HttpHelper } from "../helpers/HttpHelper";
import { HttpInterceptor } from "./HttpInterceptor.service";
@Injectable()
export class ProductService {
public emitter: EventEmitter<any> = new EventEmitter();
private APIUrl:String;
constructor(
private _http: HttpInterceptor
) {
}
getProduct(id:number): Observable<Product> {
let headers = HttpHelper.createAuthorizationHeader(true, false);
let options = new RequestOptions({ headers: headers });
return this._http
.get(routes.api.products + '/' + id, options)
.map(res => res.json());
}
/**
* Get all products
* return Observable
*/
getProducts(filters:Object): Observable<Product[]> {
let headers = HttpHelper.createAuthorizationHeader(true, false);
let options = new RequestOptions({ headers: headers });
return this._http
.get(routes.api.products + StringHelper.convertVarsToString(filters), options)
.map(res => res.json());
}
editProduct(payload) {
let headers = HttpHelper.createAuthorizationHeader(true, false);
let options = new RequestOptions({ headers: headers });
payload['_method'] = 'PUT';
return this._http
.post(routes.api.products + '/' + payload.product.id, payload, options)
.map(res => res.json());
}
/**
* Add products to EventEmitter stream
*/
public emitProducts(products): void {
this.emitter.emit(products);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我是依赖注入HttpInterceptor类而不是基本Http类,以便使用我的拦截器中包含的自定义逻辑.这工作正常,应用程序按预期运行.我遇到的问题是当我尝试配置我的测试模块以使用此HttpInterceptor类时,会引发错误.这是我的测试模块:
import { ProductService } from "../../services/product.service";
import { TestBed } from "@angular/core/testing";
import { HttpModule, Http, BaseRequestOptions } from "@angular/http";
import { MockBackend } from "@angular/http/testing";
import {HttpInterceptor} from "../../services/HttpInterceptor.service";
import {AuthService} from "../../services/auth.service";
import {GlobalEventsManager} from "../../services/globalEventsManager.service";
describe('Service: productService', () => {
let prodService: ProductService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [
{
provide: HttpInterceptor,
useFactory: (mockBackend, options, _authService, _globalEventsManager) => {
return new HttpInterceptor(mockBackend, options, _authService, _globalEventsManager);
},
deps: [MockBackend, BaseRequestOptions, AuthService, GlobalEventsManager]
},
MockBackend,
BaseRequestOptions,
ProductService
]
});
});
});
Run Code Online (Sandbox Code Playgroud)
我知道我需要在configureTestingModule方法中提供HttpInterceptor类,以使此测试起作用.不幸的是,这会导致错误.正如您所看到的,我正在使用useFactory自己创建HttpInterceptor的实例,并提供所有需要的依赖项(MockBackend,BaseRequestOptions,AuthService,GlobalEventsManager).我不确定为什么会导致错误?
我玩了一下,当我在ProductService构造函数中更改dependendy时:
@Injectable()
export class ProductService {
public emitter: EventEmitter<any> = new EventEmitter();
private APIUrl:String;
constructor(
private _http: HttpInterceptor
) {
}
Run Code Online (Sandbox Code Playgroud)
对此:
@Injectable()
export class ProductService {
public emitter: EventEmitter<any> = new EventEmitter();
private APIUrl:String;
constructor(
private _http: Http
) {
}
Run Code Online (Sandbox Code Playgroud)
然后在测试模块中提供核心Http模块,如此处所示,测试模块无误地工作.
{
provide: Http,
useFactory: (mockBackend, options) => {
return new Http(mockBackend, options);
},
deps: [MockBackend, BaseRequestOptions]
},
Run Code Online (Sandbox Code Playgroud)
这意味着将一个HttpInterceptor类的实例注入测试模块时出现问题,我无法弄清楚原因.谁能明白为什么会发生这种情况?