Directives cannot be mocked anymore
See original GitHub issueSince updating to Angular 14.2.0, all Shallow-specs for Components with Directives in their temlates are failing with this message:
Error: NG0202: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid. This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors. error properties: Object({ code: 202 })
Complete console output of ng test
✔ Browser application bundle generation complete.
15 09 2022 17:29:00.958:WARN [karma]: No captured browser, open http://localhost:9876/
15 09 2022 17:29:01.094:INFO [karma-server]: Karma v6.4.0 server started at http://localhost:9876/
15 09 2022 17:29:01.095:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
15 09 2022 17:29:01.098:INFO [launcher]: Starting browser Chrome
15 09 2022 17:29:03.625:INFO [Chrome 105.0.0.0 (Mac OS 10.15.7)]: Connected on socket -8NYow9oZdd_-iePAAAB with id 17397697
Chrome 105.0.0.0 (Mac OS 10.15.7) AppComponent should create FAILED
Error: NG0202: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid.
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.
error properties: Object({ code: 202 })
Error: NG0202: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid.
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.
at ɵɵinvalidFactoryDep (node_modules/@angular/core/fesm2020/core.mjs:4798:11)
at NodeInjectorFactory.factory (ng:///MockOfTestDirective/ɵfac.js:4:47)
at getNodeInjectable (node_modules/@angular/core/fesm2020/core.mjs:3523:44)
at instantiateAllDirectives (node_modules/@angular/core/fesm2020/core.mjs:12689:27)
at createDirectivesInstances (node_modules/@angular/core/fesm2020/core.mjs:12113:5)
at ɵɵelementStart (node_modules/@angular/core/fesm2020/core.mjs:15243:9)
at ɵɵelement (node_modules/@angular/core/fesm2020/core.mjs:15298:5)
at templateFn (ng:///AppComponent.js:371:9)
at executeTemplate (node_modules/@angular/core/fesm2020/core.mjs:12084:9)
at renderView (node_modules/@angular/core/fesm2020/core.mjs:11906:13)
Chrome 105.0.0.0 (Mac OS 10.15.7): Executed 2 of 2 (1 FAILED) (0.107 secs / 0.098 secs)
TOTAL: 1 FAILED, 1 SUCCESS
Output of ng version
Angular CLI: 14.2.2
Node: 16.17.0
Package Manager: npm 8.19.2
OS: darwin x64
Angular: 14.2.2
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1402.2
@angular-devkit/build-angular 14.2.2
@angular-devkit/core 14.2.2
@angular-devkit/schematics 14.2.2
@schematics/angular 14.2.2
rxjs 7.5.6
typescript 4.7.4
Minimal reproduction of the problem
ng new shallow-test --defaults
cd shallow-test
ng generate directive test
echo "<div appTest></div>" >> src/app/app.component.html
npm i --save-dev shallow-render
Paste this into app.component.spec.ts
:
import { Shallow } from 'shallow-render';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
describe('AppComponent', () => {
let shallow: Shallow<AppComponent>;
beforeEach(() => {
shallow = new Shallow(AppComponent, AppModule);
});
it('should create', async () => {
const { instance } = await shallow.render();
expect(instance).toBeTruthy();
});
});
And execute ng test
Workaround
The only solution I found is to not mock it at all:
beforeEach(() => {
shallow = new Shallow(AppComponent, AppModule).dontMock(TestDirective);
});
Issue Analytics
- State:
- Created a year ago
- Reactions:11
- Comments:12 (1 by maintainers)
Top Results From Across the Web
MockedProvider can't mock queries with client directives #3316
In our case we construct a client with a MockLink manually, but the issue was missing local resolvers (same as OP). Getting a...
Read more >How to mock directive on mock component - angular
I have mocked out the clarity tags but they have directives clrDgItems which I can't mock with directive class. <clr-dg-row *clrDgItems="let ...
Read more >Mocking – GraphQL Tools
Mock your GraphQL data based on a schema. ... Mock functions can't return a Promise anymore: it has to be a plain value....
Read more >EU Commission Decides To Mock The Public; Insists Fears ...
However, on Saturday, after widespread criticism, the EU Commission “removed” the post without an apology — but with the standard cop out of ......
Read more >Categorizing GraphQL Directives into Schema or Query Type
Looking at how directives are cateorized as query-type or ... having types injected by 3rd-party components, then it can't be done anymore.
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
Hey all, sorry for the delay in getting this fix. Debugging was tough but the fix was pretty simple. Looks like the directive constructor props weren’t being picked up by the Angular compiler so I manually added an
@Inject
directive.LMK how
v14.2.0
works for you.I looked a bit into the issue. This repo could also be used to reproduce the issue. It’s a fresh angular library created according to: https://angular.io/guide/creating-libraries
According to these Angular Docs the base classes of
@Directive/@Component
annotated classes need the annotation as well:“[…] When a class has a
@Directive()
or@Component()
decorator, the Angular compiler generates extra code to inject dependencies into the constructor. When using inheritance, Ivy needs both the parent class and the child class to apply a decorator to generate the correct code.”So is it possible that the
@Directive
annotation is missing on the classes which are extended by MockDirective? That would be Mock and MockWithStubs . But those classes are also used by MockComponent so the@Directive()
/@Component()
decorators would probably have to be set dynamic / conditional.Could anybody have a look at this? This issue is making the upgrade to angular 14 quite hard for us as we have many hundred tests using shallow-render.