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 test
will fail due to missing dependencies after you create aspec
using tools that generate it for any existing component. Known tools: angular-spec-generator and ngx-spec- Complaints about
ngModels
? That comes fromFormsModule
so if the component being tested uses that then you inject it viaimports: [FormsModule]
- If you see complaints about missing
HttpClient
and/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 fromMDBBootstrapModule
so 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
zone
orinjector
# 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 null
Usually all of this is available in
src/test.ts
and used byng test
automatically … but is you useprotractor
as the entrypoint, then you must incorporate workarounds intoe2e/protractor.conf.js
file’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.