diff --git a/packages/core/test/test_bed_spec.ts b/packages/core/test/test_bed_spec.ts index 6ef190b3f8042..ac989deb5b815 100644 --- a/packages/core/test/test_bed_spec.ts +++ b/packages/core/test/test_bed_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, Directive, ErrorHandler, Inject, InjectionToken, NgModule, Optional, Pipe, ɵdefineComponent as defineComponent, ɵsetClassMetadata as setClassMetadata, ɵtext as text} from '@angular/core'; +import {Component, Directive, ErrorHandler, Inject, Injectable, InjectionToken, NgModule, Optional, Pipe, ɵdefineComponent as defineComponent, ɵsetClassMetadata as setClassMetadata, ɵtext as text} from '@angular/core'; import {TestBed, getTestBed} from '@angular/core/testing/src/test_bed'; import {By} from '@angular/platform-browser'; import {expect} from '@angular/platform-browser/testing/src/matchers'; @@ -413,5 +413,31 @@ describe('TestBed', () => { expect(SomeDirective.hasOwnProperty('ngDirectiveDef')).toBeTruthy(); expect(SomePipe.hasOwnProperty('ngPipeDef')).toBeTruthy(); }); + + it('should clean up overridden providers for modules that are imported more than once', + () => { + + @Injectable() + class Token { + name: string = 'real'; + } + + @NgModule({ + providers: [Token], + }) + class Module { + } + + TestBed.configureTestingModule({imports: [Module, Module]}); + TestBed.overrideProvider(Token, {useValue: {name: 'fake'}}); + + expect(TestBed.get(Token).name).toEqual('fake'); + + TestBed.resetTestingModule(); + + // The providers for the module should have been restored to the original array, with + // no trace of the overridden providers. + expect((Module as any).ngInjectorDef.providers).toEqual([Token]); + }); }); }); diff --git a/packages/core/testing/src/r3_test_bed_compiler.ts b/packages/core/testing/src/r3_test_bed_compiler.ts index c2e38deb3daaf..3a607f5851d10 100644 --- a/packages/core/testing/src/r3_test_bed_compiler.ts +++ b/packages/core/testing/src/r3_test_bed_compiler.ts @@ -111,6 +111,7 @@ export class R3TestBedCompiler { private providerOverrides: Provider[] = []; private rootProviderOverrides: Provider[] = []; private providerOverridesByToken = new Map(); + private moduleProvidersOverridden = new Set>(); private testModuleType: NgModuleType; private testModuleRef: NgModuleRef|null = null; @@ -374,6 +375,11 @@ export class R3TestBedCompiler { } private applyProviderOverridesToModule(moduleType: Type): void { + if (this.moduleProvidersOverridden.has(moduleType)) { + return; + } + this.moduleProvidersOverridden.add(moduleType); + const injectorDef: any = (moduleType as any)[NG_INJECTOR_DEF]; if (this.providerOverridesByToken.size > 0) { if (this.hasProviderOverrides(injectorDef.providers)) { @@ -530,6 +536,7 @@ export class R3TestBedCompiler { } }); this.initialNgDefs.clear(); + this.moduleProvidersOverridden.clear(); this.restoreComponentResolutionQueue(); }