I have annoying error that probably by my mistake I cannot resolve. I have on simple component which is actually nothing else than a top-bar element in my web application.
This component as you can see has only one dependency, the UserService
and it uses it quite simply:
import { Component, OnInit } from '@angular/core';
import { MdButton } from '@angular2-material/button';
import { MdIcon , MdIconRegistry} from '@angular2-material/icon';
import { UserService } from '../services/index';
import { RouteConfig, ROUTER_DIRECTIVES, Router, ROUTER_PROVIDERS
} from '@angular/router-deprecated';
@Component({
moduleId: module.id,
selector: 'top-bar',
templateUrl: 'top-bar.component.html',
styleUrls: ['top-bar.component.css'],
providers: [MdIconRegistry, UserService, ROUTER_PROVIDERS],
directives: [MdButton, MdIcon, ROUTER_DIRECTIVES]
})
export class TopBarComponent implements OnInit {
constructor(private userService: UserService) {
this.userService = userService;
}
ngOnInit() {
}
/**
* Call UserService and logout() method
*/
logout() {
this.userService.logout();
}
}
As this service has also some dependencies (router etc) I had to provide them at the beforeEachProviders
method as you can see:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
} from '@angular/core/testing';
import { TopBarComponent } from './top-bar.component';
import {
Router, RootRouter, RouteRegistry, ROUTER_PRIMARY_COMPONENT
} from '@angular/router-deprecated';
import { provide } from '@angular/core';
import { SpyLocation } from '@angular/common/testing';
import { UserService } from '../services/index';
describe('Component: TopBar', () => {
beforeEachProviders(() => [
RouteRegistry,
provide(Location, { useClass: SpyLocation }),
provide(ROUTER_PRIMARY_COMPONENT, { useValue: TopBarComponent }),
provide(Router, { useClass: RootRouter }),
UserService,
TopBarComponent
]);
it('should inject the component', inject([TopBarComponent],
(component: TopBarComponent) => {
expect(component).toBeTruthy();
}));
});
When I run the test though I get this error message:
Chrome 51.0.2704 (Mac OS X 10.11.5) Component: TopBar should inject the component FAILED Error: No provider for Location! (TopBarComponent -> UserService -> Router -> Location) Error: DI Exception[......]
First of all as you can see the Location provider is provided. And secondary, why my test requires to provide (or inject) also the dependencies of the used into the tested component service?
For example if from the above test I remove the Router the even that my component doesn't use Router I'll get an error because the used service does. Then shouldn't I received the same error in the component and not only in the test?
UPDATE - CHANGE OF CODE & ERROR MESSAGE
I have manage to stop getting this error by changing my spec doe to this:
import {
beforeEach,
describe,
expect,
it,
} from '@angular/core/testing';
import { TopBarComponent } from './top-bar.component';
import { UserService } from '../services/index';
import {
Router
} from '@angular/router-deprecated';
import { Http } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';
describe('Component: TopBar', () => {
let router: any = Router;
let authHttp: any = AuthHttp;
let http: any = Http;
let component: TopBarComponent;
let service: UserService = new UserService(router, authHttp, http);
beforeEach(() => {
component = new TopBarComponent(service);
});
it('logout function should work ', () => {
let logout = component.logout;
logout();
expect(localStorage.getItem('token')).toBe(null);
});
});
But know I'm getting this error from my component:
TypeError: Cannot read property 'userService' of undefined
The mentioned error is on this function:
logout() {
this.userService.logout();
}
of my component but this is only on the test. In app it works normally. The function cannot reach constructor's parameter for some reason in my test.
kind of stack here...