我的HTTP拦截器中包含以下代码
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401 && location.href.indexOf('localhost') === -1) {
localStorage.setItem('some key', 'some data');
}
return throwError(error);
}
));
}
如您所见,如果我的状态为401并且href
不包含localhost
,那么我会将一些数据保留到localStorage
。
当我为这段代码编写单元测试用例时,问题来了,我该如何更改href
的值,以便可以验证是否正确保存了数据?
我知道有一些解决方法(使用Angular location
或编写包装器来获取location
对象。
但是我的问题是,是否或者如何在测试案例中直接模拟或更改全局位置对象?
答案 0 :(得分:0)
这不好–在类内部直接使用location或localStorage或任何全局对象。最好将它们注入构造函数中,以便在编写单元测试时可以对它们进行模拟。
首先在core.module中提供提供者的位置。如果没有core.module,请在app.module或main.ts文件中提供它。
providers: [
{ provide: "location", useValue: location }
],
然后您可以在类构造函数中插入位置
constructor(
@Inject("location") private location: Location
) {}
然后使用注入的位置
if (error.status === 401 && this.location.href.indexOf('localhost') === -1) {
localStorage.setItem('some key', 'some data');
}
现在,您可以轻松地在spec文件中模拟位置对象,并为每个测试用例更改location.href。
如果您不想将字符串“ location”用作注入器令牌以避免拼写错误,则可以改用InjectionToken提供位置。
import {InjectionToken} from '@angular/core';
export location = new InjectionToken('location');
最好将其分离到新文件中,以便您可以导入位置令牌以在app.module中提供并在拦截器处注入
providers: [
{ provide: location, useValue: location }
],