Error with angular2 testing component with Testbed

trying to learn this TestBed testing TestBed in angular -2 with a simple example and hit my first blocker. google or SO search did not give any relevant example,

So, I have a very simple header component as shown below -

 import { Component } from '@angular/core'; @Component({ selector: 'header', template: '' }) export class HeaderComponent{ public title: string; constructor(testparam: string){ this.title = 'test'; } } 

and then its specification 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'); }); }); 

Run Karma Test - Error: No provider for String! in karma.entry.js Error: No provider for String! in karma.entry.js

karma.entry.js basically just sets up a test env configuration for TestBed and then goes through each test in my specs folder, below is my 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 component class constructor, the tests will pass, so I think I am missing some preliminary configuration, which causes TestBed.createComponent(HeaderComponent) not correctly compile the component constructor with the string type parameter.

Any clue what I might be missing?


UPDATE:

if that helps anyone - based on @mrkosima's answer, my updated component class now looks lower and unit tests are all passing well now.

 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; } } 
+5
source share
1 answer

You are right that the main cause of the problem is the constructor argument.

During the instantiation of the component, Injector attempts to resolve all the dependencies listed in the constructor. Injector looks for dependencies by type in providers. Read more about DI here: https://angular.io/docs/ts/latest/guide/dependency-injection.html

This means that if the component has a constructor(authService: AuthService) { } , Injector looks for the AuthService token from the providers.

The same thing in your case - your component depends on String . But there are no providers with a String token.

Actually, it is a mistake to list a primitive type as a dependency.

OpaqueToken should be used instead

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

Configure token in module providers

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

How to enter a token into a component:

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

This is the correct use of an injection primitive.

More details here: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#opaquetoken

PS: to test your component, TITLE_TOKEN must be added to the testing module:

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

But how to create a test component and expect the title as 'test' .

+4
source

Source: https://habr.com/ru/post/1264133/


All Articles