如何将 angular2 服务注入单元测试? (RC3)

How do you inject an angular2 service into a unit test? (RC3)

我正在使用 RC3。我正在实施新的 Angular2 路由器,如下所述:https://angular.io/docs/ts/latest/guide/router.html

一切正常,但我在单元测试中遇到问题。具体来说,我无法将 Angular2 服务注入到我的单元测试中。

我的相关组件代码是:

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

@Component({
  templateUrl: ...
  styleUrls: ...
})

export class Route1DetailComponent {

  constructor(private route:ActivatedRoute) {
    console.log(route);
  }
}

我的单元测试看起来像:

import {
  expect, it, iit, xit,
  describe, ddescribe, xdescribe,
  beforeEach, beforeEachProviders, withProviders,
  async, inject
} from '@angular/core/testing';

import {ActivatedRoute} from '@angular/router';
import {Route1DetailComponent} from './route1-detail.component';
import {TestComponentBuilder} from '@angular/compiler/testing';

describe('route1-detail.component.ts', () => {

  beforeEachProviders(() => [
    {provide: ActivatedRoute, useClass: ActivatedRoute}
  ]);

  it('should instantiate component',
    async(inject([TestComponentBuilder, ActivatedRoute], (tcb:TestComponentBuilder, ar: ActivatedRoute) => {
      tcb.createAsync(Route1DetailComponent).then((fixture) => {
        expect(fixture.componentInstance instanceof Route1DetailComponent).toBe(true, 'should create Route1DetailComponent');
        console.log(ar);
    });
  })));
});

'should instantiate component' 单元测试失败。错误是:

Cannot resolve all parameters for 'ActivatedRoute'(?, ?, ?, ?, ?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'ActivatedRoute' is decorated with Injectable.

我如何让它工作?

当我不注入时 ActivatedRoute 一切正常。

谢谢。

在进行单元测试时,有时某个服务会因为未在正常环境中使用而导致问题。您可以测试它是否已被调用,而无需通过整个服务进行单元测试 运行。通过创建一个模拟 class.

来做到这一点
describe('route1-detail.component.ts', () => {

class MockActivatedRoute {}

beforeEachProviders(() => [
    {provide: ActivatedRoute, useClass: MockActivatedRoute}
  ]);

it('should instantiate component',
  async(inject([TestComponentBuilder, ActivatedRoute], (tcb:TestComponentBuilder, ar: MockActivatedRoute) => {
  tcb.createAsync(Route1DetailComponent).then((fixture) => {
    expect(fixture.componentInstance instanceof Route1DetailComponent).toBe(true, 'should create Route1DetailComponent');
    console.log(ar);
  });
})));

注意这部分:inject([TestComponentBuilder, ActivatedRoute], (tcb:TestComponentBuilder, ar: MockActivatedRoute。当代码正在寻找 ActivatedRoute 时,您正在将模拟服务传递给它。 当然,如果您专门尝试对 ActivatedRoute 本身进行单元测试,那么创建模拟服务会破坏该目的。如果它试图从该服务调用方法,您可能必须向模拟 class 添加方法或变量。