2016-07-22 124 views
4

我有这个函数调用window.location.href功能需要测试:我如何单元测试,在Angular2

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

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

有没有人有这个问题的解决方案?

回答

3

窗口是一个接口,不能被注入。你应该在测试

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

使用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; 
    } 
} 

然后要记住,配置应用模块使用真正的窗口对象

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