简体   繁体   English

Testbed的angular2测试组件出现错误

[英]error with angular2 testing component with Testbed

trying to learn this testing utility TestBed in angular-2 with a simple example and have hit my first blocker. 尝试通过一个简单的示例来学习angular-2中的此测试实用程序TestBed ,并遇到了我的第一个阻止者。 google or SO search didn't yield any matching example, google或SO搜索未产生任何匹配的示例,

so, I have a very basic component header as below - 所以,我有一个非常基本的组件header ,如下所示:

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

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

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

and then have its spec as below - 然后其规格如下-

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

running the karma test is throwing - Error: No provider for String! in karma.entry.js 运行业力测试会引发Error: No provider for String! in karma.entry.js - Error: No provider for String! in karma.entry.js Error: No provider for String! in karma.entry.js

karma.entry.js is basically just setting the test env configuration for TestBed and then goes thru each test in my spec folder, below is my karma.entry.js karma.entry.js基本上只是为TestBed设置测试环境配置,然后通过我的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;

If I remove the parameter from the constructor of the component class, the tests pass, so I am thinking that I am missing some pre-configuration thats causing the TestBed.createComponent(HeaderComponent) not to properly compile the component's constructor with the string type parameter. 如果我从组件类的构造函数中删除该参数,则测试通过,因此我认为我缺少一些预配置,这导致TestBed.createComponent(HeaderComponent)无法正确编译带有字符串类型参数的组件的构造函数。

any clue what I might be missing? 任何线索,我可能会错过什么?


UPDATE: 更新:

if it helps anyone - based on @mrkosima's answer, my updated component class now looks like below and the unit tests all pass good now :) 如果它可以帮助任何人-根据@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;
    }
}

You are right that the root cause of issue in the constructor's argument. 您认为构造函数的问题的根本原因是正确的。

During component instantiation Injector trying to resolve all dependencies listed in constructor. 在组件实例化期间, Injector试图解析构造函数中列出的所有依赖关系。 Injector looks up dependencies by type in providers. Injector按提供程序中的类型查找依赖项。 More about DI here: https://angular.io/docs/ts/latest/guide/dependency-injection.html 有关DI的更多信息,请访问: https : //angular.io/docs/ts/latest/guide/dependency-injection.html

That means if component has constructor(authService: AuthService) { } , the Injector looking for AuthService token in providers. 这意味着如果组件具有constructor(authService: AuthService) { } ,那么Injector在提供程序中寻找AuthService令牌。

The same in your case - your component depends on String . 在您的情况下也是如此-您的组件取决于String But there is no any provider with String token. 但是,没有任何具有String令牌的提供程序。

Actually, it's a mistake to list primitive type as dependency. 实际上,将原始类型列为依赖项是一个错误。

Instead of this OpaqueToken should be used 代替此OpaqueToken应该使用

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

Configure token in module providers 在模块提供程序中配置令牌

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

Than inject token in component: 比在组件中注入令牌:

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

That's the correct usage of injecting primitive. 那是注入原始体的正确用法。

More details here: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#opaquetoken 此处有更多详细信息: https : //angular.io/docs/ts/latest/guide/dependency-injection.html#!#opaquetoken

PS: to test your component the TITLE_TOKEN should be added to testing module: PS:要测试您的组件, TITLE_TOKEN添加到测试模块:

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

And than create test component and expect title as 'test' . 然后创建测试组件并期望title'test'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM