Posted under Angular
Permalink
Tags Angular, Gotcha
This post is a common point to document basic errors of the above kind.
1/ Karma tests fail to run giving the following kind of error:-
‘places-list’ is not a known element:
1. If ‘places-list’ is an Angular component, then verify that it is part of this module.
2. If ‘places-list’ is a Web Component then add “CUSTOM_ELEMENTS_SCHEMA” to the ‘@NgModule.schemas’ of this component to suppress this message. (”
<div> Places results:- </div>[ERROR ->]<places-list></places-list>
In this case the application ran but the tests failed as above, following the addition of a new component, PlacesList, which was added via ng new component, and used in the root AppComponent.
This StackOverflow post details the issue and the solution. In my case the new component needed adding to the declarations list in TestBed.configureTestingModule in app.component.spec.ts as the component was a required dependency. I had added it (or ng generate may have, I cannot recall) to the @NgModule declarations list in app.module.ts, which enabled the application to run. However the test bed needed it too.
2/ I hit a similar issue with the PlacesService. I was getting this error on the tests:
Chrome 56.0.2924 (Windows 7 0.0.0) PlacesListComponent should create FAILED
Error: No provider for PlacesService!
Error: DI Error
I used 2 different ways around this problem.
a/ I added PlacesService as a provider in places-list.component.spec.ts – this enabled both the tests and the app to work.
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PlacesListComponent ],
providers: [PlacesService]
})
.compileComponents();
}));
b/ Alternatively, I could also add PlacesService as a provider in both app.component.ts (i.e. at the top level) and the test definition, places-list-component.spec.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [PlacesService]
})
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PlacesListComponent ],
providers: [PlacesService]
})
.compileComponents();
}));
Whilst b/ defines the provider in 2 places, from basic knowledge this feels better as in a/ the provider is defined in the component that uses the service which feels almost as closely coupled as if I was not using DI at all.
Interestingly, when I removed the PlacesService as a provider from app.components.ts and added it to the @NgModule as a provider, in app.module.ts, this failed similarly. This was strange as I expected app.module.ts to declare the provider globally (expect perhaps for the testbeds).
This needs further looking into and understanding of the DI concepts – on the face of it, the providers (which are the actual lists of components to be injected) should be as decoupled as possible from the classes where they are used. At the moment, a lot of what I am seeing looks far too incestuous, coming from a background in Java/Spring where Spring is entirely external and responsible for the ‘provider list’.
Leave a Reply
You must be logged in to post a comment.