diff --git a/packages/core/test/test_bed_spec.ts b/packages/core/test/test_bed_spec.ts index 6d360229a0..5874e4e888 100644 --- a/packages/core/test/test_bed_spec.ts +++ b/packages/core/test/test_bed_spec.ts @@ -307,6 +307,35 @@ describe('TestBed', () => { expect(SimpleService.ngOnDestroyCalls).toBe(0); }); + it('should be able to create a fixture if a test module is reset mid-compilation', async () => { + const token = new InjectionToken('value'); + + @Component({template: 'hello {{_token}}'}) + class TestComponent { + constructor(@Inject(token) public _token: number) {} + } + + TestBed.resetTestingModule(); // Reset the state from `beforeEach`. + + function compile(tokenValue: number) { + return TestBed + .configureTestingModule({ + declarations: [TestComponent], + providers: [{provide: token, useValue: tokenValue}], + teardown: {destroyAfterEach: true} + }) + .compileComponents(); + } + + const initialCompilation = compile(1); + TestBed.resetTestingModule(); + await initialCompilation; + await compile(2); + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + expect(fixture.nativeElement).toHaveText('hello 2'); + }); + describe('module overrides using TestBed.overrideModule', () => { @Component({ selector: 'test-cmp', diff --git a/packages/core/testing/src/test_bed.ts b/packages/core/testing/src/test_bed.ts index 627489c3e0..61c4a05357 100644 --- a/packages/core/testing/src/test_bed.ts +++ b/packages/core/testing/src/test_bed.ts @@ -263,7 +263,8 @@ export class TestBedViewEngine implements TestBed { private _compiler: TestingCompiler = null!; private _moduleRef: NgModuleRef|null = null; - private _moduleFactory: NgModuleFactory = null!; + private _moduleFactory: NgModuleFactory|null = null; + private _pendingModuleFactory: Type|null = null; private _compilerOptions: CompilerOptions[] = []; @@ -341,7 +342,8 @@ export class TestBedViewEngine implements TestBed { this._isRoot = true; this._rootProviderOverrides = []; - this._moduleFactory = null!; + this._moduleFactory = null; + this._pendingModuleFactory = null; this._compilerOptions = []; this._providers = []; this._declarations = []; @@ -399,10 +401,16 @@ export class TestBedViewEngine implements TestBed { } const moduleType = this._createCompilerAndModule(); - return this._compiler.compileModuleAndAllComponentsAsync(moduleType) - .then((moduleAndComponentFactories) => { - this._moduleFactory = moduleAndComponentFactories.ngModuleFactory; - }); + this._pendingModuleFactory = moduleType; + return this._compiler.compileModuleAndAllComponentsAsync(moduleType).then(result => { + // If the module mismatches by the time the promise resolves, it means that the module has + // already been destroyed and a new compilation has started. If that's the case, avoid + // overwriting the module factory, because it can cause downstream errors. + if (this._pendingModuleFactory === moduleType) { + this._moduleFactory = result.ngModuleFactory; + this._pendingModuleFactory = null; + } + }); } private _initIfNeeded(): void {