【问题标题】:How to unit-test a function that calls window.location.href in Angular2如何对Angular2中调用window.location.href的函数进行单元测试
【发布时间】:2016-07-22 08:45:03
【问题描述】:

我有这个功能需要测试:

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();
        })
    )
  );

当我运行此测试时,我收到以下错误:

您的一些测试重新加载了整个页面!

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

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

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

有人有解决这个问题的办法吗?

【问题讨论】:

    标签: unit-testing angular jasmine window.location


    【解决方案1】:

    Window 是一个接口,不能被注入。你应该使用 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');
      }));
    });
    

    记得配置app模块使用真实的window对象

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

    【讨论】:

      猜你喜欢
      • 2017-01-21
      • 1970-01-01
      • 2017-05-16
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多