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

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

Closed
wants to merge 1 commit into from
Closed

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

wants to merge 1 commit into from

Conversation

Goodwine
Copy link

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.

Fixes #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 Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

TestBed.get(ChangeDetectorRef) // returns any

Issue Number: #26491, #29905

What is the new behavior?

// Now deprecated
TestBed.get(ChangeDetectorRef) // returns any

TestBed.inject(ChangeDetectorRef) // returns ChangeDetectorRef

Does this PR introduce a breaking change?

  • Yes
  • No

The breaking change affects a feature that has been deprecated since Angular 4.x
Injector#get() has 2 signatures:

  • Typed signature, accept an InjectionToken<T> and a class (Type<T>)
  • Anything else is also accepted but typed as any

The updated Typed signature now also accepts abstract classes (AbstractType<T>) which may cause compilation issues to the deprecated use of any as it would need to be manually downcasted to the concrete type if needed.

Other information

Internal doc - go/testbed.inject

Note: I did not update all uses of TestBed.get in the Angular codebase to keep this diff small.
I will follow with another CL migrating all TestBed.get to TestBed.inject if this PR goes through.

@Goodwine Goodwine requested review from a team as code owners August 19, 2019 23:35
@Goodwine Goodwine requested a review from a team as a code owner August 20, 2019 01:20
@atscott atscott added area: testing Issues related to Angular testing features, such as TestBed action: review The PR is still awaiting reviews from at least one requested reviewer target: major This PR is targeted for the next major release labels Aug 21, 2019
@ngbot ngbot bot modified the milestone: needsTriage Aug 21, 2019
@atscott atscott requested a review from mhevery August 21, 2019 18:26
@@ -677,7 +677,7 @@ describe('AppComponent', () => {
});

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this change is needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the "breaking changes" comment, I added AbstractType<T> to the "typed version" of Injector#get. Previously abstract classes would have returned any, the untyped version has been deprecated since Angular 4.x

This caused the returned value here to be type ElementsLoader which I thought I could cast directly to TestElementsLoader but they are apparently not fully compatible since the compiler complained about it

@mhevery mhevery self-assigned this Aug 21, 2019
@mhevery mhevery removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Aug 21, 2019
@mhevery
Copy link
Contributor

mhevery commented Aug 21, 2019

presubmit

@mhevery
Copy link
Contributor

mhevery commented Aug 21, 2019

This PR breaks a lot of things in google3 need to investigate more before it can be merged.

@Goodwine
Copy link
Author

It can be caused by:

  • Change in Injector#get, abstract classes now return the abstract type and need to be downcasted, this could cause compilation errors, I looked at the breakages and it seems like it's unproper typing that caused it.
  • It will make all TestBed.get calls deprecated which would "break" all presubmits that block on TSLint

The former can be fixed by using proper typings, the latter can be solved by not marking TestBed.get in this commit and do it after migrating all of google3

@Goodwine
Copy link
Author

Discussed with Misko, I'll remove the deprecation in this PR and fix breakages. Once it's merged, then I'll migrate google3 code, and then send another PR deprecating TestBed.get

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.
Copy link
Contributor

@IgorMinar IgorMinar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we change this so that #get behavior is unmodified while #inject projects a type-safe implementation?

I don't think that we can change the behavior of the #get api without causing lots of breakages.

@@ -295,7 +295,7 @@ describe('ViewContainerRef', () => {
const changeDetector = ref.injector.get(ChangeDetectorRef);
changeDetector.detectChanges();
expect(dynamicComp.doCheckCount).toEqual(1);
expect(changeDetector.context).toEqual(dynamicComp);
expect((changeDetector as any).context).toEqual(dynamicComp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change tells me that this is a painful breaking change that will likely affect lots of code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is Injector.get, not TestBed, the change here is that we're now taking abstract classes in consideration to return the right type instead of returning any which is the deprecated behavior since Angular 4.x

I actually don't expect many breakages from Injector.get

Copy link
Author

@Goodwine Goodwine Aug 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, this only broke 5-6 targets on google3, affecting about 10-15 files which I already fixed.

@Goodwine
Copy link
Author

Can't we change this so that #get behavior is unmodified while #inject projects a type-safe implementation?

This is what this commit is doing, I discussed with Vikram (see doc linked at the bottom of the PR) and he had the concern that TestBed.get is just too big to break, so we could add TestBed.inject and deprecate TestBed.get, the deprecation would happen on a separate commit.

@mhevery
Copy link
Contributor

mhevery commented Aug 23, 2019

presubmit

@mhevery
Copy link
Contributor

mhevery commented Aug 28, 2019

presubmit

@mhevery mhevery added the action: merge The PR is ready for merge by the caretaker label Aug 28, 2019
@mhevery
Copy link
Contributor

mhevery commented Aug 28, 2019

Can you do a global search and replace in the angular code base to switch all of the documentation example and tests to use the new inject API? Also add a note to it. Maybe do it in separate PR so that we can land this independently?

@Goodwine
Copy link
Author

I have written the PR for that - #32382
One of the AIO tests was failing because the type wasn't found, I'm suspecting it needs this one submitted because I believe it might be pulling the types from HEAD, no?

@mhevery mhevery closed this in 3aba7eb Aug 29, 2019
@Goodwine Goodwine deleted the testbed.inject branch August 29, 2019 05:07
sabeersulaiman pushed a commit to sabeersulaiman/angular that referenced this pull request Sep 6, 2019
…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 angular#26491
Fixes angular#29905

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

PR Close angular#32200
kyliau pushed a commit to angular/angular-cli that referenced this pull request Sep 9, 2019
matsko pushed a commit that referenced this pull request Sep 9, 2019
matsko pushed a commit that referenced this pull request Sep 12, 2019
From 9.0.0 use TestBed.inject
See #32200

Fixes #26491

PR Close #32406
arnehoek pushed a commit to arnehoek/angular that referenced this pull request Sep 26, 2019
…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 angular#26491
Fixes angular#29905

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

PR Close angular#32200
arnehoek pushed a commit to arnehoek/angular that referenced this pull request Sep 26, 2019
arnehoek pushed a commit to arnehoek/angular that referenced this pull request Sep 26, 2019
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: testing Issues related to Angular testing features, such as TestBed cla: yes target: major This PR is targeted for the next major release
Projects
None yet
5 participants