3

There is foo module which contains lines that cannot be tested when it's loaded as Node.js module:

if (typeof module !== 'object') {
  do.something(); // line shows as uncovered
}
...

This line cannot be normally tested with require('./foo') because module is always truthy and cannot be mocked outside the module without hooking into Node module loader.

So I have to evaluate it without require to have full control over module local variables:

const fooSource = fs.readFileSync(fooPath);
new Function('module', fooSource)();
expect(do.something).toHaveBeenCalled();

This works but this test is ignored by test coverage.

As I understand it, Jest code coverage (Istanbul) hooks into Node.js module loader and decorates module body with coverage statements, e.g.:

if (typeof module !== 'object') {
  cov_v50bukkd.f[2]++;
  do.something(); // shows as uncovered
}

How can the coverage be enabled for this line?

I would prefer not to just mark foo with 100% coverage but make it real coverage if possible, like decorating fooSource with coverage statements manually.

I proceed from the fact that foo source code shouldn't be modified to favour code coverage; it's already testable enough in other respects.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565

1 Answers1

1

In such cases, you can explicitly set NODE_ENV=test for your testing suite. Jest automatically sets NODE_ENV as such so you may enforce code coverage as:

if (typeof module !== 'object' || process.NODE_ENV === 'test') {
  do.something(); // line shows as uncovered
}
vorillaz
  • 6,098
  • 2
  • 30
  • 46
  • Thanks. I suppose this would be the most simple solution but it doesn't answer the question. I have no problems with testing this line, just with getting test coverage. Also that the line should be tested doesn't mean that is should run every time in Jest, but this will happen with `NODE_ENV=test`. As the question says, *I proceed from the fact that foo source code shouldn't be modified to favour code coverage*. I would like to address the problem stated in the question itself, at least for the sake of self-education. – Estus Flask Sep 17 '18 at 12:28
  • It actually answers how can you report coverage for this particular case. As far as I am concerned, coverage reporting tools such as Istanbul decorate everything with coverage statements and helpers functions in order to statically analyze your code. I don't think that decorating your source code in order to support Istanbul is a good idea. By the way, take a look at conditional comments, they are commonly used in order to guide Istanbul's decorators. https://github.com/gotwarlost/istanbul#ignoring-code-for-coverage – vorillaz Sep 17 '18 at 12:44
  • I see real problem with decorating the code manually but it seems that it's not possible to get Istanbul instance to do that. Please, consider updating the answer with comment option, I suppose this is most viable approach here that can be generally recommended, seems to be used in similar cases like UMD wrapper. – Estus Flask Sep 17 '18 at 15:10