Компоненты Jasmine компилируют / создают странные действия с beforeAll / beforeEach - PullRequest
0 голосов
/ 13 марта 2019

Я пишу какой-то модульный тест для моего приложения, и я столкнулся с довольно странной ситуацией. Я создал угловое приложение и использую карму и жасмин для юнит / интеграционных тестов.

Вот сделка: Я написал этот код

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();
    });

И все работает нормально, тесты компилируются и выполняются правильно (и проходят). Хотя, я полагаю, они занимают некоторое время, потому что каждый тестирующий модуль снова настраивается и компоненты компилируются.

Так что попытался изменить это так:

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

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

Эта версия той же логики / API, которая вызывается, хотя и завершается с ошибкой getTestBed (). CreateComponent, завершается с:

 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 - асинхронный / ожидание работает нормально, beforeach вызывается только после того, как beforeAll закончено 2- каждый тест дает эту ошибку выше, даже первую (что очень странно, потому что логически первый не должен менять дюйм между двумя версиями

Одна вещь, которую я заметил, заключается в том, что тесты первой версии выполняются случайным образом, тогда как вторая версия, похоже, следует порядку. Асинхронизация на foreach второй версии ничего не меняет, также я попытался вызвать различные методы сброса / уничтожения, но, похоже, ни один из них не помог.

Знаете ли вы, почему это происходит? Это нормально, если это не может быть решено, это, в конце концов, небольшая оптимизация при рассмотрении всего процесса сборки, мне более любопытно, почему это происходит.

РЕДАКТИРОВАТЬ: После анализа дополнительных данных, глядя на экземпляр testBed, я заметил, что реализация beforeEach only имеет

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 голосов
/ 16 апреля 2019

Я на самом деле обнаружил, что проблема может быть найдена здесь https://github.com/angular/angular/issues/12409

По сути, в общем, angular фактически переопределяет функцию beforeEach, добавляя некоторое очень самоуверенное поведение.В частности, здесь написано: https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L24

По этой причине тестовый модуль, настроенный в beforeAll, фактически сбрасывается в beforeEach (перед вызовом createComponent).Вместо этого использование только beforeEach действительно работает, потому что модуль настроен после вызова сброса.

Так что, либо вы используете beforeEach по назначению, жертвуя скоростью (угловое мнение заключается в том, что предоставляемые сервисы должны быть свежими при каждом тесте, что не делаетсмысл для вещей без состояния), или вы можете выбрать 2 различных решения: 1) заново определить глобальное beforeEach, восстановить его по умолчанию, а затем вернуть угловое поведение: это, конечно, хак, довольно нестабильный и выдает случайные ошибки, так какangular предполагает, что модули являются свежими для своих внутренних объектов 2) вообще не используют beforeEach, сконфигурируйте модуль в beforeAll и затем потребуйте все действия beforeEach для пользовательской функции, которую вы вызываете для каждого оператора it

...