As of Feb 2019, episodes in the 13.x range on CodeCraft.tv are the best resource, known to me, for learning: How to test components in Angular7.
But even after absorbing all that goodness, I still found it difficult to add tests in an existing project. Most of it had to do with watch ng test fail and then figuring out all the dependencies that were unaccounted for.
Here is a list of gotchas:
ng testwill fail due to missing dependencies after you create aspecusing tools that generate it for any existing component. Known tools: angular-spec-generator and ngx-spec- Complaints about
ngModels? That comes fromFormsModuleso if the component being tested uses that then you inject it viaimports: [FormsModule] - If you see complaints about missing
HttpClientand/orHttpHandler, instead of configuring theproviders:beforeEach(async () => { TestBed.configureTestingModule({ declarations: [...], imports: [], providers: [ HttpClient, HttpHandler ] }).compileComponents(); });You should configure the
imports:beforeEach(async () => { TestBed.configureTestingModule({ declarations: [...], imports: [ HttpClientModule ], providers: [...] }).compileComponents(); }); - Complaints about
mdbModal? That comes fromMDBBootstrapModuleso if the component being tested uses that then you inject it viaimports: [MDBBootstrapModule.forRoot()] - For material-design-bootstrap, if you misconfigure it as
imports:[MDBBootstrapModule]then you will see random errors like:Error: StaticInjectorError(DynamicTestModule)[ModalDirective -> ComponentLoaderFactory]: StaticInjectorError(Platform: core)[ModalDirective -> ComponentLoaderFactory]: NullInjectorError: No provider for ComponentLoaderFactory!While the real issues is that it should be initialized with
forRoot()beforeEach(async () => { TestBed.configureTestingModule({ declarations: [...], imports: [ //MDBBootstrapModule // NO! NO! MDBBootstrapModule.forRoot() // YES ], providers: [...] }).compileComponents(); }); - Complaints about
routerLink?- Don’t use the combination of
imports:[RouterModule]andproviders:[Router] - Use
imports:[RouterTestingModule.withRoutes(routes)] - You can view CodeCraft episode 13.13 to watch this done the right way.
- Don’t use the combination of
- Complaints about
zoneorinjector# can't find the zone dependency Failed: Zone is needed for the async() test helper but could not be found. Please make sure that your environment includes zone.js/dist/zone.js # testbed hasn't been initialized Failed: Cannot read property 'injector' of nullUsually all of this is available in
src/test.tsand used byng testautomatically … but is you useprotractoras the entrypoint, then you must incorporate workarounds intoe2e/protractor.conf.jsfile’sonPrepare()method somehow.- Relevant Stack Overflow posts
- https://stackoverflow.com/questions/40699593/cannot-read-property-injector-of-null-jasmine-angular-2#answer-40699740
- https://github.com/angular/quickstart/blob/master/karma-test-shim.js#L75
- https://github.com/angular/quickstart/blob/master/karma-test-shim.js#L75
- https://stackoverflow.com/questions/40699593/cannot-read-property-injector-of-null-jasmine-angular-2#answer-40699740
- Relevant Stack Overflow posts
- TBD…
Written with StackEdit.