question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Directives cannot be mocked anymore

See original GitHub issue

Since 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:closed
  • Created a year ago
  • Reactions:11
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

7reactions
getsafcommented, Dec 18, 2022

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.

2reactions
jebnercommented, Dec 15, 2022

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.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found