Dependency injection with @Self() is broken in tests
See original GitHub issue🐞 bug report
Affected Package
Is this a regression?
Unknown
Description
The @Self()
decorator does not work in tests to inject dependencies from directives placed on a component by a test-specific wrapper component.
E.g. if a I have a custom form control that injects NgControl
using the @Self()
decorator, as recommended by the Angular team:
constructor(@Self() ngControl: NgControl) {
ngControl.valueAccessor = this;
}
And I try to use this in a test wrapper component:
@Component({
template: `
<form>
<app-hello [formControl]="ctrl" name="test"></app-hello>
</form>
`
})
class TestWrapper {
ctrl = new FormControl('');
}
describe('HelloComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, ReactiveFormsModule],
declarations: [
HelloComponent,
TestWrapperComponent
],
}).compileComponents();
}));
});
Then test will fail due to an inability to inject NgControl.
🔬 Minimal Reproduction
https://github.com/jonrimmer/di-is-broken
If you run the app, you will see that it works fine.
If you run the test, you will see that it fails due to an inability to inject NgControl
into the custom form control.
🔥 Exception or Error
Chrome 75.0.3770 (Mac OS X 10.14.5) HelloComponent should create FAILED
No provider for NgControl ("[ERROR ->]<app-hello></app-hello>"): @0:0
error properties: Object({ ngSyntaxError: true, ngParseErrors: [ No provider for NgControl ("[ERROR ->]<app-hello></app-hello>"): @0:0 ] })
🌍 Your Environment
Angular Version:
Angular CLI: 8.0.6
Node: 12.4.0
OS: darwin x64
Angular: 8.0.3
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.800.6
@angular-devkit/build-angular 0.800.6
@angular-devkit/build-optimizer 0.800.6
@angular-devkit/build-webpack 0.800.6
@angular-devkit/core 8.0.6
@angular-devkit/schematics 8.0.6
@angular/cli 8.0.6
@ngtools/webpack 8.0.6
@schematics/angular 8.0.6
@schematics/update 0.800.6
rxjs 6.4.0
typescript 3.4.5
webpack 4.30.0
Anything else relevant?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:12 (4 by maintainers)
Top Results From Across the Web
Dependency Injection Bad Practices | by Luís Soares - Medium
Solution: Dependencies should be created and injected in a single place/file, usually the app's entry point, i.e, “main” (i.e. the composition root). The...
Read more >Unit tests break when I add new dependency to controller
I'm doing all my dependency injection using constructor-based injection. Thus far it's going well, but I've found myself doing something ...
Read more >Use Dependency Injection to Make Your Code Testable
Dependency injection is a pretty straightforward yet incredibly powerful technique. In short, rather than a function having its dependencies ...
Read more >Favor real dependencies for unit testing - Stack Overflow Blog
Only the imperative shell needs dependency injection to support unit testing. Which dependencies are required?
Read more >Make services unit testable using dependency injection
This means that at the time of testing, you need to isolate your class from other classes it might call (a.k.a. its dependencies)....
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@mhevery I cannot, because the injection problem is happening in tests, as indicated by the issue title and description, and Stackblitz has no capability to run Angular unit tests… The linked repo is a
ng new
project with a single, simple commit applied. The bug text also already includes the description of what I am injecting and what is going wrong.I spent considerable effort and time creating this simplified example. I find your suggestion that I didn’t, and that I’m asking you to perform unreasonable reverse engineering rude and unfounded. If your team doesn’t have the capacity to handle bug reports from the community, then you shouldn’t accept them, instead of insulting community members who make good-faith attempts to contribute.
In case anybody finds this useful, I’m able to fix this using
TestbedStatic.overrideComponent
: