【问题标题】:How do you inject an angular2 service into a unit test? (RC3)如何将 angular2 服务注入单元测试? (RC3)
【发布时间】:2016-10-31 00:57:22
【问题描述】:

我正在使用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);
    });
  })));
});

“应该实例化组件”单元测试失败。错误是:

无法解析“ActivatedRoute”的所有参数(?、?、?、?、?)。 确保所有参数都用 Inject 修饰或具有 有效的类型注释,并且 'ActivatedRoute' 装饰有 可注射。

我如何让它工作?

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

谢谢。

【问题讨论】:

标签: angular typescript angular2-routing angular2-testing angular2-di


【解决方案1】:

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

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 本身进行单元测试,那么创建模拟服务会破坏该目的。如果模拟类尝试从该服务调用方法,您可能必须向模拟类添加方法或变量。

【讨论】:

  • 很高兴帮助@danday74
  • 这太棒了!如果您使用路由参数,您将如何修改 MockActivatedRoute?
  • 我还没有测试过这个,但你可以尝试这样的事情,这样你就可以从模拟路由中调用一个假参数。如果您还订阅 params,它会变得更加复杂,但我相信它可以完成。类 MockActivatedRoute { params(){} }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 2016-05-29
相关资源
最近更新 更多