Angular 2 CLI Jasmine 单元测试在使用 beforeAll 而不是 beforeEach 时失败
Angular 2 CLI Jasmine unit test fails when using beforeAll instead of beforeEach
我使用 NG-CLI (beta.15) 创建了一个新项目并修改了 app.component.spec
以将 beforeEach
更改为 beforeAll
并导致测试失败出现以下错误:
Failed: Cannot create the component AppComponent as it was not imported into the testing module!
我不明白这个错误是什么意思,当然也不明白为什么我会首先得到它。
这是修改后的规范:
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!');
}));
});
然后我将规范修改为此,前两个测试通过,第三个失败并显示以下消息:
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!');
}));
});
我不明白为什么会失败。
不知不觉,Angular其实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();
});
}
我什至还没有尝试过这个,但如果你想知道它是如何工作的,也许可以尝试并(安全地)禁用这个功能,这就是我想出来的:
您在配置中的某处导入了
@angular/core/bundles/core-testing.umd.js
这在 karma-test-shim.js
文件中多次出现。该文件几乎包含我们在 Angular 测试中使用的所有测试实用程序。它几乎是从 testing module 导出的所有内容的汇编。这包括上面添加全局 beforeEach
调用的测试文件。
如果从上面的信息中看不出来你的beforeAll
只适合第一次测试,那么Angular会重置测试台。因此,下一个测试您将尝试从空测试台配置创建组件。
对于正在寻找真正阻止 angular 重置测试平台的方法的人:see this article
相关部分:
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());
};
我使用 NG-CLI (beta.15) 创建了一个新项目并修改了 app.component.spec
以将 beforeEach
更改为 beforeAll
并导致测试失败出现以下错误:
Failed: Cannot create the component AppComponent as it was not imported into the testing module!
我不明白这个错误是什么意思,当然也不明白为什么我会首先得到它。
这是修改后的规范:
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!');
}));
});
然后我将规范修改为此,前两个测试通过,第三个失败并显示以下消息:
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!');
}));
});
我不明白为什么会失败。
不知不觉,Angular其实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();
});
}
我什至还没有尝试过这个,但如果你想知道它是如何工作的,也许可以尝试并(安全地)禁用这个功能,这就是我想出来的:
您在配置中的某处导入了
@angular/core/bundles/core-testing.umd.js
这在 karma-test-shim.js
文件中多次出现。该文件几乎包含我们在 Angular 测试中使用的所有测试实用程序。它几乎是从 testing module 导出的所有内容的汇编。这包括上面添加全局 beforeEach
调用的测试文件。
如果从上面的信息中看不出来你的beforeAll
只适合第一次测试,那么Angular会重置测试台。因此,下一个测试您将尝试从空测试台配置创建组件。
对于正在寻找真正阻止 angular 重置测试平台的方法的人:see this article
相关部分:
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());
};