8

I'm getting this error when running a jasmine spec in angular 2:

Cannot read property 'injector' of null jasmine angular 2

stack trace:

TypeError: Cannot read property 'injector' of null
    at TestBed._createCompilerAndModule (http://localhost:3002/node_modules/@angular/core/bundles/core-testing.umd.js:834:48)
    at TestBed._initIfNeeded (http://localhost:3002/node_modules/@angular/core/bundles/core-testing.umd.js:800:43)
    at TestBed.createComponent (http://localhost:3002/node_modules/@angular/core/bundles/core-testing.umd.js:884:18)
    at Function.TestBed.createComponent (http://localhost:3002/node_modules/@angular/core/bundles/core-testing.umd.js:714:33)
    at Object.eval (http://localhost:3002/js/app/landing-page/subcomponents/middle-row.component.spec.js:29:49)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:232:26)
    at ProxyZoneSpec.onInvoke (http://localhost:3002/node_modules/zone.js/dist/proxy.js:79:39)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:231:32)
    at Zone.run (http://localhost:3002/node_modules/zone.js/dist/zone.js:114:43)
    at Object.eval (http://localhost:3002/node_modules/zone.js/dist/jasmine-patch.js:102:34)

I have copied this spec from the official angular 2 testing docs:

let comp:    BannerComponent;
let fixture: ComponentFixture<BannerComponent>;
let de:      DebugElement;
let el:      HTMLElement;

describe('BannerComponent', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ BannerComponent ], // declare the test component
    });

    fixture = TestBed.createComponent(BannerComponent);

    comp = fixture.componentInstance; // BannerComponent test instance

    // query for the title <h1> by CSS element selector
    de = fixture.debugElement.query(By.css('h1'));
    el = de.nativeElement;

  });
});

and adapted it ever so slightly to work with my code:

import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { MiddleRowComponent } from './middle-row.component';

let comp: MiddleRowComponent;
let fixture: ComponentFixture<MiddleRowComponent>;
let de: DebugElement;
let el: HTMLElement;

describe('MiddleRowComponent', () => {
   beforeEach(() => {
      TestBed.configureTestingModule({
         declarations: [MiddleRowComponent], // declare the test component
      });

      fixture = TestBed.createComponent(MiddleRowComponent);

      comp = fixture.componentInstance; // MiddleRowComponent test instance

      // query for the title <h1> by CSS element selector
      de = fixture.debugElement.query(By.css('h1'));
      el = de.nativeElement;
   });

   it('should display original title', () => {
      fixture.detectChanges();
      expect(el.textContent).toContain(comp.word);
   });

   it('should display a different test title', () => {
      comp.word = 'Test Title';
      fixture.detectChanges();
      expect(el.textContent).toContain('Test Title');
   });
});

Why am I getting the error? There is no inject keyword but I guess the TestBed might use it behind the scenes.

BeniaminoBaggins
  • 11,202
  • 41
  • 152
  • 287

1 Answers1

17

At some point (prior to any tests being executed) you need to initial the testing environment, by calling TestBed.initTestEnvironment(...).

You would normally see this done in a karma-test-shim file, as seen in the angular quickstart (same quickstart from testing docs). But if you're not using this technique, then you need to do this in your test files. But the initTestEnvironment should only be called once, so you need to also reset it in each test file

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

beforeAll(() => {
  TestBed.resetTestEnvironment();
  TestBed.initTestEnvironment(BrowserDynamicTestingModule,
                              platformBrowserDynamicTesting());
});
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks. I'm just experiencing this error now: `file:app/landing-page/subcomponents/middle-row.component.spec.ts' severity: 'Error' message: 'Argument of type '(extraProviders?: Provider[]) => PlatformRef' is not assignable to parameter of type 'PlatformRef'. Property 'bootstrapModuleFactory' is missing in type '(extraProviders?: Provider[]) => PlatformRef'.' at: '26,34' source: 'ts'` I must be needing to add something to my bootstrap of the app? `platformBrowserDynamic().bootstrapModule(AppModule);`? – BeniaminoBaggins Nov 20 '16 at 02:14
  • Sorry, the second arg should be a method _call_, not just the method. I fixed it – Paul Samsotha Nov 20 '16 at 02:19
  • It is probably the solution, I'm just trying to get [another issue](http://stackoverflow.com/q/40700142/3935156) sorted out so that I can verify that it worked. Some weird stuff is happening when I import test classes from @angular. Thanks. – BeniaminoBaggins Nov 20 '16 at 02:49
  • beforeAll is not defined :P Sorry my environment must be terribly UNset up for testing. I'm trying to sort out this issue. Seems like it's usually due to an old version of Jasmine however in my `package.json devDependencies` I have `"jasmine": "~2.0.0",`, and I deleted node_modules and did a clean install – BeniaminoBaggins Nov 20 '16 at 03:33
  • Really you could just put it before the describe. It doesn't need to be in a beforeall. You could even put it in beforeeach, but it might lead to bad performance in the tests – Paul Samsotha Nov 20 '16 at 04:00
  • Really you should just look into using the testshim file like the one I linked to I. The quickstart – Paul Samsotha Nov 20 '16 at 04:02
  • I knew there was a correct solution on one of my questions I was forgetting about! – BeniaminoBaggins Nov 30 '16 at 04:38