7

I am testing an angular project with jest (using jest-preset-angular).

When collecting coverage, I get an uncovered branch and I don't understand why. I can reproduce the problem with 3 files.

some-dependency.ts

export class SomeDependency {}

some-service.ts

import { Injectable } from '@angular/core';
import { SomeDependency } from './some-dependency';

@Injectable()
export class SomeService {
    constructor(private dependency: SomeDependency) {
        console.log('service created');
    }
}

some-service.spec

import { SomeService } from './some-service';

describe('DerivedClass', () => {
    it('should create', () => {
        expect(new SomeService(null)).toBeTruthy();
    });
});

by running yarn jest --coverage some-service, I get following coverage:

--------------------|----------|----------|----------|----------|-------------------|
File                |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
--------------------|----------|----------|----------|----------|-------------------|
All files           |      100 |       75 |      100 |      100 |                   |
 some-dependency.ts |      100 |      100 |      100 |      100 |                   |
 some-service.ts    |      100 |       75 |      100 |      100 |                 6 |
--------------------|----------|----------|----------|----------|-------------------|

in the HTML report, I get too little information on what is uncovered.

enter image description here

I noticed that removing @Injectable decorator makes the coverage back to 100%

Does someone have an explanation? Is there a way to get my 100% coverage while keeping @Injectable decorator?

Edit: I have added a console.log to prove the constructor is properly invoked. The yellow highlight is given by Istambul report and helps to see the uncovered branch. But there is no branch to me here since there is no condition.

Sergio Mazzoleni
  • 1,458
  • 15
  • 24

2 Answers2

5

By comparing with the brand new project created by @markusdresch where coverage is 100% indeed, I finally found that one ts-jest option set in jest.config.js causes side effect on code coverage.

{
    // ...
    globals: {
        'ts-jest': {
            // ...
            isolatedModules: true,
        },
    },
}

isolatedModules set to true causes the uncovered branch described in the original question. By setting it to false or removing it, coverage is back to 100%.

I wish I could use isolatedModules = true and still have a 100% coverage, but I guess this should be a brand new question.

Sergio Mazzoleni
  • 1,458
  • 15
  • 24
  • FYI, the reason I want to use `isolatedModules` is related to this [question](https://stackoverflow.com/questions/57442151/i-cannot-configure-jest-properly-to-import-modules-setupfilesafterenv) – Sergio Mazzoleni Aug 16 '19 at 11:24
  • Hi @sergio-mazzoleni , have you had any chance to make isolatedModules = true work with 100% coverage? Unfortunately, disabling it in my case generates a huge memory heap because of the size of the project and I don't need type-hinting in tests – Joseph Aug 16 '21 at 07:41
  • @Joseph no, sorry, I gave up because I was using `isolatedModules: true` as a workaround for another problem, but I finally fixed the "root" issue [here](https://stackoverflow.com/a/59041659/3572918) – Sergio Mazzoleni Aug 16 '21 at 08:10
  • I've solved by disabling decorators in my tsconfig.test.json and mocking them. Now I can keep `isolatedModules: true`. I don't need type-hinting in jest (the build process is enough already) and the performance without it are outstanding. – Joseph Aug 20 '21 at 16:09
1

I created a brand new Angular app, added jest-preset-angular and the tests you mention, and it's 100% code coverage.

Check out https://github.com/markusdresch/angular-jest-example

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |      100 |      100 |      100 |      100 |                   |
 app                 |      100 |      100 |      100 |      100 |                   |
  app.component.html |      100 |      100 |      100 |      100 |                   |
  app.component.ts   |      100 |      100 |      100 |      100 |                   |
 models              |      100 |      100 |      100 |      100 |                   |
  some-dependency.ts |      100 |      100 |      100 |      100 |                   |
 services            |      100 |      100 |      100 |      100 |                   |
  some.service.ts    |      100 |      100 |      100 |      100 |                   |
---------------------|----------|----------|----------|----------|-------------------|
Markus Dresch
  • 5,290
  • 3
  • 20
  • 40