unit-testing - 如何对 Angular2 中调用 window.location.href 的函数进行单元测试

标签 unit-testing angular jasmine window.location

我有这个功能需要测试:

login(): void {
    this.userService.setSessionAndDateOnlogin();
    this.loginService.getLogin()
      .subscribe(
        octopusUrl => window.location.href = octopusUrl);
  }

我使用 window.location.href 导航到外部 URL。

这是我的测试:

it('login function should call the setSessionAndDateOnLogin function from the userservice and\
   subscribe to the  getLogin function of the loginService.',
    fakeAsync(
      inject(
        [LoginComponent, LoginService, UserService],
        (loginComponent: LoginComponent, loginService: LoginService, userService: UserService) => {
          spyOn(userService, 'setSessionAndDateOnlogin');
          loginComponent.login();
          expect(userService.setSessionAndDateOnlogin).toHaveBeenCalled();
        })
    )
  );

当我运行此测试时,出现以下错误:

Some of your tests did a full page reload!

所以我尝试模拟窗口对象:

import { window } from '@angular/platform-browser/src/facade/browser';
...
class MockWindow {
  location: {
    href: ''
  };
}
...
beforeEach(() => addProviders([
    ...
    { provide: window, useClass: MockWindow }
  ]));

这没有任何改变,错误仍然存​​在。

有人能解决这个问题吗?

最佳答案

Window 是一个接口(interface),不能被注入(inject)。你应该使用 OpaqueToken

import {Injectable, OpaqueToken, Inject} from '@angular/core';

export const WindowToken = new OpaqueToken('Window');
export const SomeServiceWithWindowDependencyToken = new OpaqueToken('SomeServiceWithWindowDependency');

export function _window(): Window {
  return window;
}


export class SomeServiceWithWindowDependency {
  private window: Window;

  constructor(@Inject(WindowToken) window: Window) {
    this.window = window;
  }
}

然后在测试

describe('SomeServiceWithWindowDependency', () => {
  beforeEach(() => {
    let mockWindow: any = {
      location: {
        hostname: ''
      }
    };
    TestBed.configureTestingModule({
      providers: [
        {provide: WindowToken, useValue: mockWindow},
        {provide: SomeServiceWithWindowDependencyToken, useClass: SomeServiceWithWindowDependency}
      ]
    });
  });
  it('should do something', inject([SomeServiceWithWindowDependencyToken, WindowToken], (tested: SomeServiceWithWindowDependency, window: Window) => {
    window.location.hostname = 'localhost';
    expect(tested.someMethod()).toBe('result');
  }));
});

并且记得将应用模块配置为使用真实的窗口对象

@NgModule({
 declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    ...
    {provide: WindowToken, useFactory: _window},
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

关于unit-testing - 如何对 Angular2 中调用 window.location.href 的函数进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38522002/

相关文章:

ios - 使用 pod 时,isKindOfClass 在目标之间不匹配

java - 如何在 testet 方法中编写带有断言的单元测试?

javascript - @Input 在 ngOnInit Angular 2 上未定义

javascript - 延迟 Angular 旋转器不闪烁

javascript - 水平滚动条在 Protractor 中不起作用 - Firefox 浏览器

javascript - 在 Jest 测试中模拟节点模块

java.lang.NoSuchMethodError : 'void org.springframework.util.Assert.state(boolean, java.util.function.Supplier)' 错误

javascript - 从 Angular 对象的数据数组填充 View

javascript - 无法将参数从命令传递到 grunt 文件

jasmine - 有没有办法在 Jasmine Headless webkit 上使用调试?