单元测试/模拟Angular2中的窗口属性(TypeScript)

Rhy*_*hys 16 unit-testing phantomjs typescript karma-jasmine angular

我正在为Angular2中的服务构建一些单元测试.

在我的服务中,我有以下代码:

var hash: string; hash = this.window.location.hash;

但是,当我运行包含此代码的测试时,它将失败.

利用Window的所有功能会很棒,但是当我使用PhantomJs时,我认为这不可行(我也尝试过使用Chrome产生相同结果的功能).

在AngularJs中,我会使用模拟$ Window(或者至少是有问题的属性),但由于Angular2单元测试没有很多文档,我不知道如何做到这一点.

有人可以帮忙吗?

Kla*_*urn 24

在Angular 2中,您可以使用@Inject()函数通过使用字符串标记命名窗口对象来注入窗口对象,就像这样

  constructor( @Inject('Window') private window: Window) { }
Run Code Online (Sandbox Code Playgroud)

@NgModule您必须然后使用相同字符串,它提供:

@NgModule({
    declarations: [ ... ],
    imports: [ ... ],
    providers: [ { provide: 'Window', useValue: window } ],
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)

然后你也可以使用令牌字符串来模拟它

beforeEach(() => {
  let windowMock: Window = <any>{ };
  TestBed.configureTestingModule({
    providers: [
      ApiUriService,
      { provide: 'Window', useFactory: (() => { return windowMock; }) }
    ]
  });
Run Code Online (Sandbox Code Playgroud)

这适用于Angular 2.1.1,最新版本为2016-10-28.

不适用于Angular 4.0.0 AOT. https://github.com/angular/angular/issues/15640


elw*_*wyn 6

正如@estus在评论中提到的那样,你最好从路由器获取哈希值.但要直接回答您的问题,您需要将窗口注入您正在使用它的位置,以便在测试期间您可以模拟它.

首先,使用angular2提供程序注册窗口 - 如果你在整个地方使用它,可能是全局的:

import { provide } from '@angular/core';
provide(Window, { useValue: window });
Run Code Online (Sandbox Code Playgroud)

这告诉了当依赖注入要求类型时的角度Window,它应该返回全局window.

现在,在你正在使用它的地方,你将它注入你的类而不是直接使用全局:

import { Component } from '@angular/core';

@Component({ ... })
export default class MyCoolComponent {
    constructor (
        window: Window
    ) {}

    public myCoolFunction () {
        let hash: string;
        hash = this.window.location.hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您已准备好在测试中模拟该值.

import {
    beforeEach,
    beforeEachProviders,
    describe,
    expect,
    it,
    inject,
    injectAsync
} from 'angular2/testing';

let myMockWindow: Window;
beforeEachProviders(() => [
    //Probably mock your thing a bit better than this..
    myMockWindow = <any> { location: <any> { hash: 'WAOW-MOCK-HASH' }};
    provide(Window, {useValue: myMockWindow})
]);

it('should do the things', () => {
    let mockHash = myMockWindow.location.hash;
    //...
});
Run Code Online (Sandbox Code Playgroud)

  • [provide 在 RC6 中被删除](https://github.com/angular/angular/blob/master/CHANGELOG.md#writing-changes) 从核心中,将其更改为 `providers: [ {provide: Window, useValue: window} ,]` (2认同)

ulo*_*lou 5

在 RC4 方法之后provide()它被弃用了,所以在 RC4 之后处理这个的方法是:

  let myMockWindow: Window;

  beforeEach(() => {
    myMockWindow = <any> { location: <any> {hash: 'WAOW-MOCK-HASH'}};
    addProviders([SomeService, {provide: Window, useValue: myMockWindow}]);
  });
Run Code Online (Sandbox Code Playgroud)

我需要一段时间才能弄清楚它是如何工作的。