12

I am following this tutorial: https://angular.io/guide/testing#component-test-scenarios for karma+jasmine unit testing. Here my code:

import { AppComponent } from "./app.component";
import { ComponentFixture, TestBed } from "@angular/core/testing";

describe('AppComponent', () => {

let component: AppComponent;
let fixture:   ComponentFixture<AppComponent>;
let h1:        HTMLElement;

beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [ AppComponent ],
  });
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance; 
  h1 = fixture.nativeElement.querySelector('h1');
});

it('should display original title', () => {
    expect(h1.textContent).toContain("Ciao");
  });

});

When I run the test I get the following exception:

 TypeError: Cannot read property 'getComponentFromError' of null
    at TestBed._initIfNeeded (D:/Users/apwzp/AppData/Local/Temp/karma-typescript-bundle-11944DDd01l2f5Y0P.js:1020:52)
    at TestBed.createComponent (D:/Users/apwzp/AppData/Local/Temp/karma-typescript-bundle-11944DDd01l2f5Y0P.js:1174:14)
    at Function.TestBed.createComponent (D:/Users/apwzp/AppData/Local/Temp/karma-typescript-bundle-11944DDd01l2f5Y0P.js:876:29)
    at UserContext.<anonymous> (assets/app/app.component.spec.ts:14:20 <- assets/app/app.component.spec.js:13:37)
    at ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:388:26)
    at ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:79:39)
    at ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:387:32)
    at Zone.run (node_modules/zone.js/dist/zone.js:138:43)
    at UserContext.<anonymous> (node_modules/zone.js/dist/jasmine-patch.js:106:34)

Does anyone know how to solve it?

laumonta
  • 153
  • 1
  • 1
  • 8

3 Answers3

25

I ran into something similar and found the answer here: Cannot read property 'injector' of null jasmine angular 2.

I just added this to my beforeEach() method which solved this error for me (there were a few others I had to overcome before I got this all working entirely).

 TestBed.resetTestEnvironment();
 TestBed.initTestEnvironment(BrowserDynamicTestingModule,
    platformBrowserDynamicTesting());

Basically it was just a matter of changing this:

beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [ AppComponent ],
   });
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance; 
  h1 = fixture.nativeElement.querySelector('h1');
});

To

import { BrowserDynamicTestingModule,
platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

beforeEach(() => {
 TestBed.resetTestEnvironment();
 TestBed.initTestEnvironment(BrowserDynamicTestingModule,
    platformBrowserDynamicTesting());

  TestBed.configureTestingModule({
    declarations: [ AppComponent ],
   });
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance; 
  h1 = fixture.nativeElement.querySelector('h1');
});
mikeo
  • 1,045
  • 13
  • 17
  • That fixed it... but why...? I already had a call to `TestBed.initTestEnvironment()` in a different file and made sure that file is loaded before my `spec.ts` files. Why does moving the init code to the `.spec.ts` file fix this error? – Steven Liekens Aug 13 '18 at 13:31
  • The key here is `initTestEnvironment` which per the angular docs is required to initialize the compiler, platformRef and angular module for testing. Not sure about having to move the files around. I found this worked for me provided it is inside every files `beforeEach` or `beforeAll`. – mikeo Aug 13 '18 at 16:01
  • I already had `initTestEnvironment` but it was in a different file. I even made sure that file was loaded before my specs. Nothing worked except this answer. – Steven Liekens Aug 14 '18 at 08:57
  • I'm not entirely sure I'm answering your question but; `initTestEnvironment` needs to be run in a `beforeEach` or `beforeAll` in every `.spec` file in order to prepare the Angular environment. You can't just run it once before your specs load. – mikeo Aug 14 '18 at 16:03
  • 3
    Well why can't I just run it once before my specs load? What does it do that only works if run inside `beforeAll`? That's the part that I don't understand. – Steven Liekens Aug 15 '18 at 09:04
  • I am not sure with this answer. Because in all my tests until now, I had no issues running tests without resetting my test environment and initing the browser dynamic testing. Adding this code, did not fix my issues. – Florian Leitgeb Jun 28 '19 at 13:00
1

If you're upgrading to jest-preset-angular version >= 9, replacing import 'jest-preset-angular'; with import 'jest-preset-angular/setup-jest'; seems to solve the issue without the need to add a beforeAll to every test.

See https://github.com/thymikee/jest-preset-angular/blob/a4251dd9776fe4d99af828b43acc3ea3a1bb5f90/CHANGELOG.md#breaking-changes

Chilloutman
  • 457
  • 2
  • 13
0

Just add this to setupJest.ts in the root folder:

import {TestBed} from '@angular/core/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';

TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(BrowserDynamicTestingModule,
  platformBrowserDynamicTesting());

And then add this to the jest configuration:

"setupFilesAfterEnv": [
  "<rootDir>/setupJest.ts"
],
Jöcker
  • 5,281
  • 2
  • 38
  • 44