Angular HTTP拦截器测试-更改window.location.href值

时间:2020-05-15 15:17:07

标签: javascript angular angular8

我的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对象。

但是我的问题是,是否或者如何在测试案例中直接模拟或更改全局位置对象?

1 个答案:

答案 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 }
],