I created a new project with NG-CLI (beta.15) and modified the app.component.spec
to change the beforeEach
to to a beforeAll
and it caused the tests to fail with the following error:
Failed: Cannot create the component AppComponent as it was not imported into the testing module!
I don't understand what this error means and of course why I would get it in the first place.
Here's the modified spec:
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('App: Ng2CliTest2', () => {
beforeAll(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
});
});
it('should create the app', async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
let fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
});
I then modified the spec to this and the first two tests pass and the third fails with the following message :
Failed: Attempt to use a destroyed view: detectChanges
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
let fixture;
let app;
describe('App: Ng2CliTest2', () => {
beforeAll(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
});
fixture = TestBed.createComponent(AppComponent);
app = fixture.debugElement.componentInstance;
});
it('should create the app', async(() => {
expect(app).toBeTruthy();
}));
it(`should have as title 'app works!'`, async(() => {
expect(app.title).toEqual('app works!');
}));
it('should render title in a h1 tag', async(() => {
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('app works!');
}));
});
I don't understand why there are any failures.
Without knowing it, Angular actually resets the testing module in it's own undercover beforeEach
(see testing.ts
)
var _global = <any>(typeof window === 'undefined' ? global : window);
// Reset the test providers and the fake async zone before each test.
if (_global.beforeEach) {
_global.beforeEach(() => {
TestBed.resetTestingModule();
resetFakeAsyncZone();
});
}
I haven't even tried this, but it you want to know how it works to maybe try and (safely) disable this feature, this is what I've figured out:
Somewhere in your configuration you have imported
@angular/core/bundles/core-testing.umd.js
This is many times in a karma-test-shim.js
file. This file contains pretty much all the testing utilities we use in a Angular test. It's pretty much a compilation of everything exported from the testing module. This include the above testing file that adds a global beforeEach
call.
And just if it's not obvious from the above information your beforeAll
is only good for the first test, then Angular resets the test bed. So the next test you are trying to create a component from an empty test bed configuration.
For whoever is looking for a way to actually prevent angular from resetting the testbed: see this article
Relevant part:
import { TestBed, TestModuleMetadata } from '@angular/core/testing';
const resetTestingModule = TestBed.resetTestingModule;
const preventAngularFromResetting = () => TestBed.resetTestingModule = () => TestBed;
const allowAngularToReset = () => {
resetTestingModule();
TestBed.resetTestingModule = resetTestingModule;
};
export const setUpTestBed = (moduleDef: TestModuleMetadata, ...funcs: (() => void)[]) => {
beforeAll(done => (async () => {
resetTestingModule();
preventAngularFromResetting();
TestBed.configureTestingModule(moduleDef);
funcs.forEach(func => func());
TestBed.resetTestingModule = () => TestBed;
return await TestBed.compileComponents();
})().then(done).catch(done.fail));
afterAll(() => allowAngularToReset());
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With