Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ivy): fix proliferation of provider overrides for modules #29571

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 27 additions & 1 deletion packages/core/test/test_bed_spec.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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]);
});
});
});
7 changes: 7 additions & 0 deletions packages/core/testing/src/r3_test_bed_compiler.ts
Expand Up @@ -111,6 +111,7 @@ export class R3TestBedCompiler {
private providerOverrides: Provider[] = [];
private rootProviderOverrides: Provider[] = [];
private providerOverridesByToken = new Map<any, Provider[]>();
private moduleProvidersOverridden = new Set<Type<any>>();

private testModuleType: NgModuleType<any>;
private testModuleRef: NgModuleRef<any>|null = null;
Expand Down Expand Up @@ -374,6 +375,11 @@ export class R3TestBedCompiler {
}

private applyProviderOverridesToModule(moduleType: Type<any>): 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)) {
Expand Down Expand Up @@ -530,6 +536,7 @@ export class R3TestBedCompiler {
}
});
this.initialNgDefs.clear();
this.moduleProvidersOverridden.clear();
this.restoreComponentResolutionQueue();
}

Expand Down