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
why is a constructor parameter considered a branch and not covered? #70
Comments
|
I am having the same issue. I found some fix that uses comments to ignore lines of code like /* istanbul ignore next */ but these do not work at all. |
|
Edit: we are having a similar issue with decorators. I originally posted here but then felt it is different enough to be a separate issue. I created issue #72 . |
|
@daBishMan @EugeneSnihovsky I will make sure we have a test case around constructors in the tests for the instrumenter. Unfortunately, as with #72, when a transpiler is being used to shim language features the generated code can sometimes introduce branches that are difficult to cover -- what does the constructor ultimately look like, when run through the TypeScript compiler? |
|
I am experiencing the same issues as @EugeneSnihovsky and @daBishMan. One of the failing constructors is simple: public constructor(private renderer: Renderer2) { }and the transpiled javascript is: function SearchComponent(renderer) {
this.renderer = renderer;
}but when running coverage, I get the following result: |
|
I have exactly the same in an angular4 env. |
|
+1 I tried using |
|
Having this problem too =( wrong lines/coverage for typescript |
|
Any ETA on this issue please? |
|
I found a (quite ugly) workaround by adding constructor(@inject(TYPES.IDataProvider) private dataProvider: IDataProvider | any) {
} |
|
I'm interested by a solution too, I'm working with NestJS, and I have the same issue. |
|
Same issue here +1 NestJS edit I was able to fix my coverage issue @otroboe " Error: Nest can't resolve dependencies of the ShowController (?). Please verify whether [0] argument is available in the current context. " if you only add so it'll look something like this for a service, the It may be the case that what you lose is type-ahead and type-checking, (I didn't have that issue) but you get 100% code-coverage in return. So it's up to your discretion. |
|
+1 I'm using NestJs too |
|
I'm also having the same issue when using Jest with Angular 5 and Typescript. Is this something that is being addressed as of now or at least in the pipeline to be fixed? |
|
Seeing the same issue, making the branch metrics on the coverage report unreliable. |
|
We're seeing the same thing on Angular 5 + Jest. It's not every single line in the constructor, which is weird. Sometimes there will be three things being injected and it will just be one line or so that's showing as uncovered. |
|
Hello guys esp, @pie6k . I can confirm that i just discovered a fix for this. I was working on an open source project here forensic-js when i bumped into this problem, I had to dig in and thankfully, i was able to find a fix. Here is my Report and Fix First of all, this issue arises when your class extends another class. It does not happen if your class does not extend another class. What then is the Cause? The cause is that when a class var _this = possibleConstructorReturn(this, (_DOMTokenList.__proto__ ||
Object.getPrototypeOf(_DOMTokenList)).call(this, null, true, true));As you can see, it tries to access it using the deprecated What Then is the Fix? The fix is creating an instance of your class two times to statisfy those conditions, and thankfully, the Here is how i did it: let instance = null,
proto = MyClassName.__proto__;
//lets satisfy condition 1
MyClassName.__proto__ = null;
//put in try catch because it throws error
try {
instance = new MyClassName(...args);
}
catch(ex){}
//lets satisfy condition two, set back the proto
MyclassName.__proto__ = proto;
instance = new MyClassName(...args);Thats it. you can wrap this into a function and make it reusable across tests. Hope this makes someone smile.... lol. If you are using |
|
I'm having the same problem but I can't get your fix to work @harrison-ifeanyichukwu |
|
@mikeesouth, this issue all depends on the nature of your constructor, and a better way for me to offer any other suggestion is by having a look at the final build. if you don't mind, you can paste the line of code that is not covered here, or my email harrisonifeanyichukwu@gmail.com.. if it is an open source project, i can replicate it from my end as well if given the link. thanks. Also note that the transpiler used in my case is |
|
Hi @harrison-ifeanyichukwu, how are you doing? I'm having the same problem as well. Coverage report doesn't give a real feedback, the branch coverage in reports is 88%, but I've tested 100% of my code. I created a simulation in the following link https://github.com/rhogeranacleto/branch-not-covered-simulation, have a look into the And in Do you have any suggestion? |
|
Hi @rhogeranacleto , hope you are doing great, I have been looking into your issue, I think your problem all boils down to the use of decorators. Though it is different from my own problem and suggested fix, below is my suggestion based on my findings. The decorators introduces branching and your tests have to cover this scenerios Concerning The export declare const Get: (path?: string) => MethodDecorator;This introduces a branch. Therefore, your test should cover both situations, you should test when a path argument is supplied and when a path argument is not supplied. The second problem on the same line is that the export declare function Query(...pipes: (Type<PipeTransform> | PipeTransform)[]): any;Your test should cover both scenerio. test when the argument is of type For other similar lines, use your text editor's go to definition functionality, you will see the prototype of these decorators from your nestjs node module. and fix the issues using my logic here. Thanks I hope this rectifies your case. I would really appreciate your feedback. |
|
Who is passing by branch not covered in randoms statements just add ignoreCoverageForAllDecorators described on ts-jest documentation. Will works for the most of cases I guess. |
|
@rhogeranacleto is this still working for you? I tried it, but it didn't seem to change anything. |
|
@itslenny in some cases yes. As you can see on print screens below:
As we can see, the only thing I can't fix it is the coverage on dependency injection. Anyone with a workaround would be very pleasurable. 🙃 🙃 |
|
I ran into this issue with After some debugging, I found that but for some reason Looking at the source map visualization, it's that In any case, we solved this by setting |
|
I have the same issues with an up-to-date Nx Workspace |
|
Setting the |
@otroboe Did find a workaround for NestJS? I have the same issue but only on one service on the whole app. |
|
@walterspieler |
Thanks for your answer. It works for me. I am able to get 100% coverage 👍 |
|
Is there any update on this issue? Still seeing constructor coverage gaps with This issue seems to present on HttpClient injection, and the |
|
For anyone using Webpack with const istanbulInstrumenter = require('istanbul-instrumenter-loader');
exports.default = function(source, sourceMap) {
// Ignore decorators on methods and properties
source = source.replace(/(tslib.+\.__decorate)/g, '/* istanbul ignore next */$1');
// When constructor parameters have decorated properties (eg @inject), TS adds
// a typeof branch check, which we don't want to instrument
source = source.replace(/(typeof \(_\w\s*=)/g, '/* istanbul ignore next */$1');
istanbulInstrumenter.apply(this, [source, sourceMap]);
}Then you replace your usage of the loader in your Webpack config: |
|
I also encountered this issue. After much searching it turned out that the link to my tsconfig was incorrect. |
|
In our case the report was incorrect due to having offloaded the type-checking of TS files to a separate node process. |
|
I've ended up with this workaround (similar to what @alecgibson has). Works for anyone who use bare // fix-istanbul-decorators.js
const { default: tsJest } = require('ts-jest');
module.exports = fixIstanbulDecoratorCoverageTransformer();
function fixIstanbulDecoratorCoverageTransformer() {
const transformer = tsJest.createTransformer();
const process = transformer.process.bind(transformer);
transformer.process = (...args) => {
let result = process(...args);
// Ignore decorators on methods and properties
result = result.replace(
/__decorate/g,
'/* istanbul ignore next */__decorate',
);
// When constructor parameters have decorated properties (eg @inject), TS adds
// a typeof branch check, which we don't want to instrument
result = result.replace(
/(?<=__metadata\("design:paramtypes".*?)(typeof \(_\w\s*=)/g,
'/* istanbul ignore next */$1',
);
return result;
};
return transformer;
}// jest.config.js
...
globals: {
'ts-jest': {
isolatedModules: true,
},
},
transform: {
'\\.(ts|tsx)$': '<rootDir>/fix-istanbul-decorators.js',
},
... |
|
for // fix-istanbul-decorators.js
// See https://github.com/istanbuljs/istanbuljs/issues/70#issuecomment-975654329
const { default: tsJest } = require('ts-jest');
module.exports = fixIstanbulDecoratorCoverageTransformer();
function fixIstanbulDecoratorCoverageTransformer() {
const transformer = tsJest.createTransformer();
const process = transformer.process.bind(transformer);
transformer.process = (...args) => {
let result = process(...args);
// Ignore decorators on methods and properties
result.code = result.code.replace(/__decorate/g, '/* istanbul ignore next */__decorate');
// When constructor parameters have decorated properties (eg @inject), TS adds
// a typeof branch check, which we don't want to instrument
result.code = result.code.replace(
/(?<=__metadata\("design:paramtypes".*?)(typeof \(_\w\s*=)/g,
'/* istanbul ignore next */$1',
);
return result;
};
return transformer;
} |
|
We are facing the same issue, and this happens only when we're using The solutions provided in the comments (eg. this and this) do not seem to have any effect. @micalevisk @vad3x these solutions do not seem to have an effect on my end. This is how I solved the issue, in an Angular app. I had to specifically add |
|
Experiencing this now after upgrading from Angular 14.1 to Angular 14.2 (using Yarn workspace, not sure about npm). Any suggestions? I'm not using |
|
Hi @michaelfaith ! My hacky solution does use |
|
Thanks. I guess I thought your solution was focused on solving this for people using |
|
Recently moved from Angular 13 to Angular 14.4.0 and this is now a problem for our code coverage. Is there a fix available for this? All of my constructors are flagging up now as branches that are not covered |
What finally solved this issue for us in Angular 14.2+ was removing |
|
Yep, that solved it! Thanks very much @michaelfaith 😃 |
|
Nice @michaelfaith ! Is this valid even for |
|
I haven't tried it with |
|
Thanks @michaelfaith, it works with Angular 14 ! |
|
Hi guys, First: thank you @micalevisk for your file ! :) For my project, it was just missing one thing to work properly and to remove this warning: @sans-jmansfield I think it could solve your problem, I'm using Nest too and all is good now. My configuration: fix-istanbul-decorator.js: // eslint-disable-next-line @typescript-eslint/no-var-requires
const { default: tsJest } = require('ts-jest')
module.exports = fixIstanbulDecoratorCoverageTransformer()
function fixIstanbulDecoratorCoverageTransformer() {
// The option of isolatedModules was necessary for me
const transformer = tsJest.createTransformer({ isolatedModules: true })
const process = transformer.process.bind(transformer)
transformer.process = (...args) => {
let result = process(...args)
// Ignore decorators on methods and properties
result.code = result.code.replace(/__decorate/g, '/* istanbul ignore next */__decorate')
// When constructor parameters have decorated properties (eg @inject), TS adds
// a typeof branch check, which we don't want to instrument
result.code = result.code.replace(
/(?<=__metadata\("design:paramtypes".*?)(typeof \(_\w\s*=)/g,
'/* istanbul ignore next */$1'
)
return result
}
return transformer
}jest.config.js: module.exports = {
...,
moduleNameMapper: {
'^src(.*)$': '<rootDir>/src/$1',
// Related to this: https://jestjs.io/docs/28.x/upgrading-to-jest28#packagejson-exports
uuid: require.resolve('uuid')
},
transform: {
'\\.(ts|tsx)$': '<rootDir>/fix-istanbul-decorators.js'
},
...
}Hope it will help ! |













Hello all,
Thanks for great work, and sorry if this is not the right forum to ask this question.

As you can see from the image above, the constructor params are considered branch and are not covered, the rest of the class is 100% expect the constructor.
Can you tell me why it is counting the constructor as branches, and how can I fix it, please?
The text was updated successfully, but these errors were encountered: