Jasmine编译/创建与beforeAll / beforeEach

时间:2019-03-13 14:45:37

标签: angular jasmine karma-runner

我正在为我的应用程序编写一些单元测试,但遇到了一个非常奇怪的情况。 我构建了一个有角度的应用程序,并且正在使用业力和茉莉进行单元/集成测试。

这是交易: 我写了这段代码

describe("Body Container component", () => {
    let component: BodyContainerComponent;
    let fixture: ComponentFixture<BodyContainerComponent>;
    beforeEach(async () => {
        getTestBed().configureTestingModule({
            imports: [AppTestingModule]
        });
        await getTestBed().compileComponents();
        fixture = getTestBed().createComponent(BodyContainerComponent);
        component = fixture.componentInstance;
        component.ngOnInit();
        fixture.detectChanges();
    });

它工作正常,测试已正确编译和执行(并通过)。 但是,它们确实需要一段时间,因为每次testingModule都需要重新配置并编译组件。

因此,尝试通过这种方式进行更改:

 beforeAll(async () => {
    getTestBed().resetTestingModule();
    getTestBed().configureTestingModule({
        imports: [AppTestingModule]
    });
    await getTestBed().compileComponents();
});

beforeEach(async () => {
    fixture = getTestBed().createComponent(BodyContainerComponent);
    component = fixture.componentInstance;
    component.ngOnInit();
    fixture.detectChanges();
});

虽然在getTestBed()。createComponent上失败,但调用的相同逻辑/ API的该版本失败,并显示以下信息:

 Error: Illegal state: Could not load the summary for directive BodyContainerComponent.
    error properties: Object({ ngSyntaxError: true })
        at syntaxError (http://localhost:9876/node_modules/@angular/compiler/fesm5/compiler.js?:2430:1)
        at CompileMetadataResolver.push../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getDirectiveSummary (http://localhost:9876/node_modules/@angular/compiler/fesm5/compiler.js?:18535:1)
        at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.getComponentFactory (http://localhost:9876/node_modules/@angular/compiler/fesm5/compiler.js?:25979:1)
        at CompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.getComponentFactory (http://localhost:9876/node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js?:162:1)
        at TestingCompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/testing.js.TestingCompilerImpl.getComponentFactory (http://localhost:9876/node_modules/@angular/platform-browser-dynamic/fesm5/testing.js?:110:1)
        at TestBedViewEngine.push../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.createComponent (http://localhost:9876/node_modules/@angular/core/fesm5/testing.js?:1905:1)
        at Object.<anonymous> (http://localhost:9876/src/test/integration/app/components/body-container.integration-spec.ts?:21:32)
        at step (http://localhost:9876/node_modules/tslib/tslib.es6.js?:97:1)
        at Object.next (http://localhost:9876/node_modules/tslib/tslib.es6.js?:78:45)
        at http://localhost:9876/node_modules/tslib/tslib.es6.js?:71:1

我尝试了各种迭代和更改以使其起作用,但是错误仍然存​​在。 经过分析,我可以说: 1- async / await工作正常,仅在beforeAll完成后才调用beforeach 2-每个测试都会给出上面的错误,即使是第一个也是如此(这很奇怪,因为从逻辑上讲,第一个不应在两个版本之间改变一英寸

我注意到的一件事是,第一个版本的测试是随机执行的,而第二个版本的测试似乎是遵循顺序的。 在第二个版本的preach上,异步没有任何改变,我也尝试调用各种reset / destroy方法,但似乎没有任何贡献。

您知道为什么会这样吗? 没关系,这是可以的,毕竟是在整个构建过程中进行了微小的优化,我很好奇为什么会这样。

编辑:经过附加分析,通过查看testBed实例,我注意到“仅beforeEach”实现具有

TestBedViewEngine{_instantiated: false, _compiler: TestingCompilerImpl{_compiler: CompilerImpl{_metadataResolver: ..., _delegate: ..., injector: ...}, _directiveResolver: MockDirectiveResolver{_reflector: ..., _directives: ...}, _pipeResolver: MockPipeResolver{_reflector: ..., _pipes: ...}, _moduleResolver: MockNgModuleResolver{_reflector: ..., _ngModules: ...}, _overrider: MetadataOverrider{_references: ...}}, _moduleRef: null, _moduleFactory: NgModuleFactory_{moduleType: function DynamicTestModule() { ... }, _bootstrapComponents: [], _ngModuleDefFactory: function(_l) { ... }}, _compilerOptions: [], _moduleOverrides: [], _componentOverrides: [], _directiveOverrides: [], _pipeOverrides: [], _providers: [], _declarations: [], _imports: [function AppTestingModule() { ... }], _schemas: [], _activeFixtures: [], _testEnvAotSummaries: function () { ... }, _aotSummaries: [], _templateOverrides: [], _isRoot: true, _rootProviderOverrides: [], platform: PlatformRef{_injector: StaticInjector{parent: ..., source: ..., _records: ...}, _modules: [], _destroyListeners: [], _destroyed: false}, ngModule: function BrowserDynamicTestingModule() { ... }}

而beforeAll具有:

TestBedViewEngine{_instantiated: false, _compiler: null, _moduleRef: null, _moduleFactory: null, _compilerOptions: [], _moduleOverrides: [], _componentOverrides: [], _directiveOverrides: [], _pipeOverrides: [], _providers: [], _declarations: [], _imports: [], _schemas: [], _activeFixtures: [], _testEnvAotSummaries: function () { ... }, _aotSummaries: [], _templateOverrides: [], _isRoot: true, _rootProviderOverrides: [], platform: PlatformRef{_injector: StaticInjector{parent: ..., source: ..., _records: ...}, _modules: [], _destroyListeners: [], _destroyed: false}, ngModule: function BrowserDynamicTestingModule() { ... }}

通过此输出可以看到的最大区别是_compiler,它分别为null和实例化。 该TestBed“快照”是在createComponent调用之前进行的

1 个答案:

答案 0 :(得分:0)

我实际上发现了问题,可以在这里https://github.com/angular/angular/issues/12409

总的来说,角度实际上是在每个函数之前重新定义角度,从而增加了一些自以为是的行为。具体来说,它写在这里:https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L24

因此,在beforeAll中配置的测试模块实际上会在beforeEach(在createComponent调用之前)重置。 而是只使用beforeEach实际上有效,因为该模块是在reset调用之后配置的。

因此,您可以按预期的方式使用beforeEach,但是会牺牲速度(普遍认为,每次测试中提供的服务应该是新鲜的,这对于无状态的东西没有意义),或者您可以选择两种不同的解决方案: 1)再次在beforeEach之前重新定义全局,将其恢复为默认值,然后放回角度行为:这当然是hack,非常不稳定并且会引发随机错误,因为angular假设模块对于自己的内部是新鲜的 2)根本不使用beforeEach,在beforeAll中配置模块,然后将所有beforeEach活动要求给您在每个it语句上调用的自定义函数