带有Testbed的angular2测试组件出错

时间:2017-02-12 19:23:57

标签: angular karma-jasmine testbed

尝试使用一个简单的例子在angular-2中学习这个测试实用程序TestBed并且击中了我的第一个阻止程序。 google或SO搜索没有产生任何匹配的示例,

所以,我有一个非常基本的组件header,如下所示 -

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

@Component({
    selector: 'header',
    template: ''
})
export class HeaderComponent{
    public title: string;

    constructor(testparam: string){
        this.title = 'test';
    }
}

然后将其规格如下 -

import { TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';

describe('HeaderComponent Test', () => {
    let component: HeaderComponent;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [HeaderComponent]
        });

        const fixture = TestBed.createComponent(HeaderComponent);
        component = fixture.componentInstance;
    });

    it('should have the component defined', () => {
        expect(component).toBeDefined();
    });

    it('should initialize the title to test', () => {
        expect(component.title).toBe('test');
    });
});
  

运行业力测试就是投掷 - Error: No provider for String! in karma.entry.js

karma.entry.js基本上只是为TestBed设置测试env配置,然后通过我的spec文件夹中的每个测试,下面是我的karma.entry.js

require('core-js/es6');
require('core-js/es7/reflect');

require('es6-shim');
require('reflect-metadata');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
require('rxjs/Rx');

const browserTesting = require('@angular/platform-browser-dynamic/testing');
const coreTesting = require('@angular/core/testing');

coreTesting.TestBed.initTestEnvironment(
   browserTesting.BrowserDynamicTestingModule,
   browserTesting.platformBrowserDynamicTesting()
);

const context = require.context('../src', true, /\.spec\.ts$/);

context.keys().forEach(context);

Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;

如果我从组件类的构造函数中删除参数,测试会通过,所以我认为我缺少一些导致TestBed.createComponent(HeaderComponent)无法正确编译组件的预配置。带有字符串类型参数的构造函数。

我可能遗失的任何线索?

更新

如果有帮助的话 - 根据@ mrkosima的回答,我更新的组件类现在看起来如下,单元测试现在通过好了:)

import { Component,  OpaqueToken, Inject } from '@angular/core';

export let TITLE_TOKEN = new OpaqueToken('title token');

@Component({
    selector: 'header',
    template: '',
    providers: [{ provide: TITLE_TOKEN, useValue: 'test' }]
})
export class HeaderComponent{
    public title: string;

    constructor(@Inject(TITLE_TOKEN) titleParam: string){
        this.title = titleParam;
    }
}

1 个答案:

答案 0 :(得分:5)

你在构造函数的参数中找出问题的根本原因是正确的。

在组件实例化Injector期间尝试解析构造函数中列出的所有依赖项。 Injector按提供程序中的类型查找依赖项。 有关DI的更多信息,请访问:https://angular.io/docs/ts/latest/guide/dependency-injection.html

这意味着如果组件有constructor(authService: AuthService) { },则Injector会在提供商中查找AuthService令牌。

在您的情况下相同 - 您的组件取决于String。 但是没有任何提供商使用String令牌。

实际上,将原始类型列为依赖是错误的。

应使用

而不是OpaqueToken
export let TITLE_TOKEN = new OpaqueToken('title token');

在模块提供程序中配置令牌

providers: [{ provide: TITLE_TOKEN, useValue: 'title value' }]

比在组件中注入令牌:

constructor(@Inject(TITLE_TOKEN) title: string) {
  this.title = title;
}

这是注入原语的正确用法。

此处有更多详情: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#opaquetoken

PS:要测试组件,应将TITLE_TOKEN添加到测试模块中:

import {TITLE_TOKEN} from ...
TestBed.configureTestingModule({
      providers: [ { provide: TITLE_TOKEN, useValue: 'test' } ]
});

而不是创建测试组件,并期望title'test'