feat(core): Introduce TestBed.inject to replace TestBed.get (#32200)

TestBed.get is not type safe, fixing it would be a massive breaking
change. The Angular team has proposed replacing it with TestBed.inject
and deprecate TestBed.get.

Deprecation from TestBed.get will come as a separate commit.

Issue #26491
Fixes #29905

BREAKING CHANGE: Injector.get now accepts abstract classes to return
type-safe values. Previous implementation returned `any` through the
deprecated implementation.

PR Close #32200
This commit is contained in:
Carlos Ortiz García 2019-08-19 15:05:29 -07:00 committed by Misko Hevery
parent 2b28b91fd9
commit 3aba7ebe6a
10 changed files with 132 additions and 79 deletions

View File

@ -677,7 +677,7 @@ describe('AppComponent', () => {
}); });
it('should not be loaded/registered until necessary', () => { it('should not be loaded/registered until necessary', () => {
const loader: TestElementsLoader = fixture.debugElement.injector.get(ElementsLoader); const loader = fixture.debugElement.injector.get(ElementsLoader) as unknown as TestElementsLoader;
expect(loader.loadCustomElement).not.toHaveBeenCalled(); expect(loader.loadCustomElement).not.toHaveBeenCalled();
setHasFloatingToc(true); setHasFloatingToc(true);

View File

@ -601,7 +601,8 @@ export class ApplicationRef {
this.componentTypes.push(componentFactory.componentType); this.componentTypes.push(componentFactory.componentType);
// Create a factory associated with the current module if it's not bound to some other // Create a factory associated with the current module if it's not bound to some other
const ngModule = isBoundToModule(componentFactory) ? null : this._injector.get(NgModuleRef); const ngModule =
isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef);
const selectorOrNode = rootSelectorOrNode || componentFactory.selector; const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule); const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Type} from '../interface/type'; import {AbstractType, Type} from '../interface/type';
import {stringify} from '../util/stringify'; import {stringify} from '../util/stringify';
import {resolveForwardRef} from './forward_ref'; import {resolveForwardRef} from './forward_ref';
@ -55,7 +55,8 @@ export abstract class Injector {
* @returns The instance from the injector if defined, otherwise the `notFoundValue`. * @returns The instance from the injector if defined, otherwise the `notFoundValue`.
* @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`. * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.
*/ */
abstract get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): T; abstract get<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
/** /**
* @deprecated from v4.0.0 use Type<T> or InjectionToken<T> * @deprecated from v4.0.0 use Type<T> or InjectionToken<T>
* @suppress {duplicate} * @suppress {duplicate}

View File

@ -299,7 +299,7 @@ describe('ViewContainerRef', () => {
const changeDetector = ref.injector.get(ChangeDetectorRef); const changeDetector = ref.injector.get(ChangeDetectorRef);
changeDetector.detectChanges(); changeDetector.detectChanges();
expect(dynamicComp.doCheckCount).toEqual(1); expect(dynamicComp.doCheckCount).toEqual(1);
expect(changeDetector.context).toEqual(dynamicComp); expect((changeDetector as any).context).toEqual(dynamicComp);
}); });
it('should not throw when destroying a reattached component', () => { it('should not throw when destroying a reattached component', () => {

View File

@ -11,6 +11,7 @@
// this statement only. // this statement only.
// clang-format off // clang-format off
import { import {
AbstractType,
Component, Component,
Directive, Directive,
InjectFlags, InjectFlags,
@ -49,7 +50,7 @@ const UNDEFINED: Symbol = Symbol('UNDEFINED');
* Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3` * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
* according to the compiler used. * according to the compiler used.
*/ */
export class TestBedRender3 implements Injector, TestBed { export class TestBedRender3 implements TestBed {
/** /**
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
* angular module. These are common to every test in the suite. * angular module. These are common to every test in the suite.
@ -150,15 +151,26 @@ export class TestBedRender3 implements Injector, TestBed {
return TestBedRender3 as any as TestBedStatic; return TestBedRender3 as any as TestBedStatic;
} }
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
|null;
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T|null,
flags?: InjectFlags): T|null {
return _getTestBedRender3().inject(token, notFoundValue, flags);
}
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
static get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; static get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
/** /** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
* @deprecated from v8.0.0 use Type<T> or InjectionToken<T>
*/
static get(token: any, notFoundValue?: any): any; static get(token: any, notFoundValue?: any): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
static get( static get(
token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND, token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND,
flags: InjectFlags = InjectFlags.Default): any { flags: InjectFlags = InjectFlags.Default): any {
return _getTestBedRender3().get(token, notFoundValue); return _getTestBedRender3().inject(token, notFoundValue, flags);
} }
static createComponent<T>(component: Type<T>): ComponentFixture<T> { static createComponent<T>(component: Type<T>): ComponentFixture<T> {
@ -244,22 +256,33 @@ export class TestBedRender3 implements Injector, TestBed {
compileComponents(): Promise<any> { return this.compiler.compileComponents(); } compileComponents(): Promise<any> { return this.compiler.compileComponents(); }
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; inject<T>(
/** token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
* @deprecated from v8.0.0 use Type<T> or InjectionToken<T> inject<T>(
*/ token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
get(token: any, notFoundValue?: any): any; |null;
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND, inject<T>(
flags: InjectFlags = InjectFlags.Default): any { token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T|null,
if (token === TestBedRender3) { flags?: InjectFlags): T|null {
return this; if (token as unknown === TestBedRender3) {
return this as any;
} }
const result = this.testModuleRef.injector.get(token, UNDEFINED, flags); const result = this.testModuleRef.injector.get(token, UNDEFINED, flags);
return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) : result; return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) : result;
} }
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get(token: any, notFoundValue?: any): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND,
flags: InjectFlags = InjectFlags.Default): any {
return this.inject(token, notFoundValue, flags);
}
execute(tokens: any[], fn: Function, context?: any): any { execute(tokens: any[], fn: Function, context?: any): any {
const params = tokens.map(t => this.get(t)); const params = tokens.map(t => this.inject(t));
return fn.apply(context, params); return fn.apply(context, params);
} }
@ -299,7 +322,7 @@ export class TestBedRender3 implements Injector, TestBed {
} }
createComponent<T>(type: Type<T>): ComponentFixture<T> { createComponent<T>(type: Type<T>): ComponentFixture<T> {
const testComponentRenderer: TestComponentRenderer = this.get(TestComponentRenderer); const testComponentRenderer = this.inject(TestComponentRenderer);
const rootElId = `root-ng-internal-isolated-${_nextRootElementId++}`; const rootElId = `root-ng-internal-isolated-${_nextRootElementId++}`;
testComponentRenderer.insertRootElement(rootElId); testComponentRenderer.insertRootElement(rootElId);
@ -310,11 +333,12 @@ export class TestBedRender3 implements Injector, TestBed {
`It looks like '${stringify(type)}' has not been IVY compiled - it has no 'ngComponentDef' field`); `It looks like '${stringify(type)}' has not been IVY compiled - it has no 'ngComponentDef' field`);
} }
// TODO: Don't cast as `any`, proper type is boolean[] // TODO: Don't cast as `InjectionToken<boolean>`, proper type is boolean[]
const noNgZone = this.get(ComponentFixtureNoNgZone as any, false); const noNgZone = this.inject(ComponentFixtureNoNgZone as InjectionToken<boolean>, false);
// TODO: Don't cast as `any`, proper type is boolean[] // TODO: Don't cast as `InjectionToken<boolean>`, proper type is boolean[]
const autoDetect: boolean = this.get(ComponentFixtureAutoDetect as any, false); const autoDetect: boolean =
const ngZone: NgZone|null = noNgZone ? null : this.get(NgZone as Type<NgZone|null>, null); this.inject(ComponentFixtureAutoDetect as InjectionToken<boolean>, false);
const ngZone: NgZone|null = noNgZone ? null : this.inject(NgZone, null);
const componentFactory = new ComponentFactory(componentDef); const componentFactory = new ComponentFactory(componentDef);
const initComponent = () => { const initComponent = () => {
const componentRef = const componentRef =

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ApplicationInitStatus, CompilerOptions, Component, Directive, InjectFlags, InjectionToken, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetInjectableDef as getInjectableDef, ɵivyEnabled as ivyEnabled, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify, ɵɵInjectableDef} from '@angular/core'; import {AbstractType, ApplicationInitStatus, CompilerOptions, Component, Directive, InjectFlags, InjectionToken, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetInjectableDef as getInjectableDef, ɵivyEnabled as ivyEnabled, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify, ɵɵInjectableDef} from '@angular/core';
import {AsyncTestCompleter} from './async_test_completer'; import {AsyncTestCompleter} from './async_test_completer';
import {ComponentFixture} from './component_fixture'; import {ComponentFixture} from './component_fixture';
@ -56,16 +56,15 @@ export interface TestBed {
compileComponents(): Promise<any>; compileComponents(): Promise<any>;
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
|null;
// TODO: switch back to official deprecation marker once TSLint issue is resolved /** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
// https://github.com/palantir/tslint/issues/4522 get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
/** /** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
* deprecated from v8.0.0 use Type<T> or InjectionToken<T>
* This does not use the deprecated jsdoc tag on purpose
* because it renders all overloads as deprecated in TSLint
* due to https://github.com/palantir/tslint/issues/4522.
*/
get(token: any, notFoundValue?: any): any; get(token: any, notFoundValue?: any): any;
execute(tokens: any[], fn: Function, context?: any): any; execute(tokens: any[], fn: Function, context?: any): any;
@ -104,7 +103,7 @@ export interface TestBed {
* Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3` * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
* according to the compiler used. * according to the compiler used.
*/ */
export class TestBedViewEngine implements Injector, TestBed { export class TestBedViewEngine implements TestBed {
/** /**
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
* angular module. These are common to every test in the suite. * angular module. These are common to every test in the suite.
@ -216,16 +215,29 @@ export class TestBedViewEngine implements Injector, TestBed {
return TestBedViewEngine as any as TestBedStatic; return TestBedViewEngine as any as TestBedStatic;
} }
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
|null;
static inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T|null,
flags?: InjectFlags): T|null {
return _getTestBedViewEngine().inject(token, notFoundValue, flags);
}
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
static get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; static get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
/** /**
* @deprecated from v8.0.0 use Type<T> or InjectionToken<T> * TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject
* @suppress {duplicate} * @suppress {duplicate}
*/ */
static get(token: any, notFoundValue?: any): any; static get(token: any, notFoundValue?: any): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
static get( static get(
token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND, token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND,
flags: InjectFlags = InjectFlags.Default): any { flags: InjectFlags = InjectFlags.Default): any {
return _getTestBedViewEngine().get(token, notFoundValue, flags); return _getTestBedViewEngine().inject(token, notFoundValue, flags);
} }
static createComponent<T>(component: Type<T>): ComponentFixture<T> { static createComponent<T>(component: Type<T>): ComponentFixture<T> {
@ -431,8 +443,7 @@ export class TestBedViewEngine implements Injector, TestBed {
class DynamicTestModule { class DynamicTestModule {
} }
const compilerFactory: TestingCompilerFactory = const compilerFactory = this.platform.injector.get(TestingCompilerFactory);
this.platform.injector.get(TestingCompilerFactory);
this._compiler = compilerFactory.createTestingCompiler(this._compilerOptions); this._compiler = compilerFactory.createTestingCompiler(this._compilerOptions);
for (const summary of [this._testEnvAotSummaries, ...this._aotSummaries]) { for (const summary of [this._testEnvAotSummaries, ...this._aotSummaries]) {
this._compiler.loadAotSummaries(summary); this._compiler.loadAotSummaries(summary);
@ -454,16 +465,17 @@ export class TestBedViewEngine implements Injector, TestBed {
} }
} }
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; inject<T>(
/** token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
* @deprecated from v8.0.0 use Type<T> or InjectionToken<T> inject<T>(
*/ token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
get(token: any, notFoundValue?: any): any; |null;
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND, inject<T>(
flags: InjectFlags = InjectFlags.Default): any { token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T|null,
flags?: InjectFlags): T|null {
this._initIfNeeded(); this._initIfNeeded();
if (token === TestBed) { if (token as unknown === TestBed) {
return this; return this as any;
} }
// Tests can inject things from the ng module and from the compiler, // Tests can inject things from the ng module and from the compiler,
// but the ng module can't inject things from the compiler and vice versa. // but the ng module can't inject things from the compiler and vice versa.
@ -471,9 +483,19 @@ export class TestBedViewEngine implements Injector, TestBed {
return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue, flags) : result; return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue, flags) : result;
} }
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get(token: any, notFoundValue?: any): any;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND,
flags: InjectFlags = InjectFlags.Default): any {
return this.inject(token, notFoundValue, flags);
}
execute(tokens: any[], fn: Function, context?: any): any { execute(tokens: any[], fn: Function, context?: any): any {
this._initIfNeeded(); this._initIfNeeded();
const params = tokens.map(t => this.get(t)); const params = tokens.map(t => this.inject(t));
return fn.apply(context, params); return fn.apply(context, params);
} }
@ -575,12 +597,13 @@ export class TestBedViewEngine implements Injector, TestBed {
`Cannot create the component ${stringify(component)} as it was not imported into the testing module!`); `Cannot create the component ${stringify(component)} as it was not imported into the testing module!`);
} }
// TODO: Don't cast as `any`, proper type is boolean[] // TODO: Don't cast as `InjectionToken<boolean>`, declared type is boolean[]
const noNgZone = this.get(ComponentFixtureNoNgZone as any, false); const noNgZone = this.inject(ComponentFixtureNoNgZone as InjectionToken<boolean>, false);
// TODO: Don't cast as `any`, proper type is boolean[] // TODO: Don't cast as `InjectionToken<boolean>`, declared type is boolean[]
const autoDetect: boolean = this.get(ComponentFixtureAutoDetect as any, false); const autoDetect: boolean =
const ngZone: NgZone|null = noNgZone ? null : this.get(NgZone as Type<NgZone|null>, null); this.inject(ComponentFixtureAutoDetect as InjectionToken<boolean>, false);
const testComponentRenderer: TestComponentRenderer = this.get(TestComponentRenderer); const ngZone: NgZone|null = noNgZone ? null : this.inject(NgZone, null);
const testComponentRenderer: TestComponentRenderer = this.inject(TestComponentRenderer);
const rootElId = `root${_nextRootElementId++}`; const rootElId = `root${_nextRootElementId++}`;
testComponentRenderer.insertRootElement(rootElId); testComponentRenderer.insertRootElement(rootElId);
@ -658,7 +681,7 @@ export function inject(tokens: any[], fn: Function): () => any {
// Return an async test method that returns a Promise if AsyncTestCompleter is one of // Return an async test method that returns a Promise if AsyncTestCompleter is one of
// the injected tokens. // the injected tokens.
return testBed.compileComponents().then(() => { return testBed.compileComponents().then(() => {
const completer: AsyncTestCompleter = testBed.get(AsyncTestCompleter); const completer = testBed.inject(AsyncTestCompleter);
testBed.execute(tokens, fn, this); testBed.execute(tokens, fn, this);
return completer.promise; return completer.promise;
}); });

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Component, Directive, InjectFlags, InjectionToken, NgModule, Pipe, PlatformRef, SchemaMetadata, Type} from '@angular/core'; import {AbstractType, Component, Directive, InjectFlags, InjectionToken, NgModule, Pipe, PlatformRef, SchemaMetadata, Type} from '@angular/core';
import {ComponentFixture} from './component_fixture'; import {ComponentFixture} from './component_fixture';
import {MetadataOverride} from './metadata_override'; import {MetadataOverride} from './metadata_override';
@ -114,15 +114,15 @@ export interface TestBedStatic {
deps?: any[], deps?: any[],
}): TestBedStatic; }): TestBedStatic;
inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
inject<T>(
token: Type<T>|InjectionToken<T>|AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T
|null;
/** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any; get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
// TODO: switch back to official deprecation marker once TSLint issue is resolved /** TODO(goodwine): Mark as deprecated from v9.0.0 use TestBed.inject */
// https://github.com/palantir/tslint/issues/4522
/**
* deprecated from v8.0.0 use Type<T> or InjectionToken<T>
* This does not use the deprecated jsdoc tag on purpose
* because it renders all overloads as deprecated in TSLint
* due to https://github.com/palantir/tslint/issues/4522.
*/
get(token: any, notFoundValue?: any): any; get(token: any, notFoundValue?: any): any;
createComponent<T>(component: Type<T>): ComponentFixture<T>; createComponent<T>(component: Type<T>): ComponentFixture<T>;

View File

@ -776,7 +776,7 @@ class HiddenModule {
const mock = ref.injector.get(HttpTestingController) as HttpTestingController; const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
const http = ref.injector.get(HttpClient); const http = ref.injector.get(HttpClient);
ref.injector.get<NgZone>(NgZone).run(() => { ref.injector.get<NgZone>(NgZone).run(() => {
http.get('http://localhost/testing').subscribe((body: string) => { http.get<string>('http://localhost/testing').subscribe((body: string) => {
NgZone.assertInAngularZone(); NgZone.assertInAngularZone();
expect(body).toEqual('success!'); expect(body).toEqual('success!');
}); });
@ -791,8 +791,8 @@ class HiddenModule {
platform.bootstrapModule(HttpClientExampleModule).then(ref => { platform.bootstrapModule(HttpClientExampleModule).then(ref => {
const mock = ref.injector.get(HttpTestingController) as HttpTestingController; const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
const http = ref.injector.get(HttpClient); const http = ref.injector.get(HttpClient);
ref.injector.get<NgZone>(NgZone).run(() => { ref.injector.get(NgZone).run(() => {
http.get('http://localhost/testing').subscribe((body: string) => { http.get<string>('http://localhost/testing').subscribe((body: string) => {
expect(body).toEqual('success!'); expect(body).toEqual('success!');
}); });
expect(ref.injector.get<NgZone>(NgZone).hasPendingMacrotasks).toBeTruthy(); expect(ref.injector.get<NgZone>(NgZone).hasPendingMacrotasks).toBeTruthy();
@ -808,8 +808,8 @@ class HiddenModule {
platform.bootstrapModule(HttpInterceptorExampleModule).then(ref => { platform.bootstrapModule(HttpInterceptorExampleModule).then(ref => {
const mock = ref.injector.get(HttpTestingController) as HttpTestingController; const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
const http = ref.injector.get(HttpClient); const http = ref.injector.get(HttpClient);
ref.injector.get<NgZone>(NgZone).run(() => { ref.injector.get(NgZone).run(() => {
http.get('http://localhost/testing').subscribe((body: string) => { http.get<string>('http://localhost/testing').subscribe((body: string) => {
NgZone.assertInAngularZone(); NgZone.assertInAngularZone();
expect(body).toEqual('success!'); expect(body).toEqual('success!');
}); });

View File

@ -456,7 +456,7 @@ export declare class InjectionToken<T> {
} }
export declare abstract class Injector { export declare abstract class Injector {
abstract get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): T; abstract get<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
/** @deprecated */ abstract get(token: any, notFoundValue?: any): any; /** @deprecated */ abstract get(token: any, notFoundValue?: any): any;
static NULL: Injector; static NULL: Injector;
static THROW_IF_NOT_FOUND: Object; static THROW_IF_NOT_FOUND: Object;

View File

@ -58,9 +58,11 @@ export interface TestBed {
configureTestingModule(moduleDef: TestModuleMetadata): void; configureTestingModule(moduleDef: TestModuleMetadata): void;
createComponent<T>(component: Type<T>): ComponentFixture<T>; createComponent<T>(component: Type<T>): ComponentFixture<T>;
execute(tokens: any[], fn: Function, context?: any): any; execute(tokens: any[], fn: Function, context?: any): any;
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
get(token: any, notFoundValue?: any): any; get(token: any, notFoundValue?: any): any;
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
initTestEnvironment(ngModule: Type<any> | Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void; initTestEnvironment(ngModule: Type<any> | Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void;
inject<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
inject<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T | null;
overrideComponent(component: Type<any>, override: MetadataOverride<Component>): void; overrideComponent(component: Type<any>, override: MetadataOverride<Component>): void;
overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): void; overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): void;
overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void; overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void;
@ -93,17 +95,15 @@ export interface TestBedStatic {
}): TestBedStatic; }): TestBedStatic;
configureTestingModule(moduleDef: TestModuleMetadata): TestBedStatic; configureTestingModule(moduleDef: TestModuleMetadata): TestBedStatic;
createComponent<T>(component: Type<T>): ComponentFixture<T>; createComponent<T>(component: Type<T>): ComponentFixture<T>;
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
get(token: any, notFoundValue?: any): any; get(token: any, notFoundValue?: any): any;
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): any;
initTestEnvironment(ngModule: Type<any> | Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): TestBed; initTestEnvironment(ngModule: Type<any> | Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): TestBed;
inject<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue: null, flags?: InjectFlags): T | null;
inject<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue?: T, flags?: InjectFlags): T;
overrideComponent(component: Type<any>, override: MetadataOverride<Component>): TestBedStatic; overrideComponent(component: Type<any>, override: MetadataOverride<Component>): TestBedStatic;
overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): TestBedStatic; overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): TestBedStatic;
overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): TestBedStatic; overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): TestBedStatic;
overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): TestBedStatic; overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): TestBedStatic;
overrideProvider(token: any, provider: {
useFactory: Function;
deps: any[];
}): TestBedStatic;
overrideProvider(token: any, provider: { overrideProvider(token: any, provider: {
useValue: any; useValue: any;
}): TestBedStatic; }): TestBedStatic;
@ -112,6 +112,10 @@ export interface TestBedStatic {
useValue?: any; useValue?: any;
deps?: any[]; deps?: any[];
}): TestBedStatic; }): TestBedStatic;
overrideProvider(token: any, provider: {
useFactory: Function;
deps: any[];
}): TestBedStatic;
overrideTemplate(component: Type<any>, template: string): TestBedStatic; overrideTemplate(component: Type<any>, template: string): TestBedStatic;
overrideTemplateUsingTestingModule(component: Type<any>, template: string): TestBedStatic; overrideTemplateUsingTestingModule(component: Type<any>, template: string): TestBedStatic;
resetTestEnvironment(): void; resetTestEnvironment(): void;