[Angular, Jest] TypeError: Cannot read property 'ɵprov' of undefined のエラーを解決

## 要約
Angularのサービスクラスに対するテストコードを作っていたとき、以下のエラーでハマりました。

```
TypeError: Cannot read property 'ɵprov' of undefined
```
または

```
Can't resolve all parameters for HeroService: (?).
```

~~結論から言うと、原因は分かっていないのですが、サービスクラスの`@Injectable`内部の記述を以下のように変更することで解消しました。~~

```diff
@Injectable({ 
-  providedIn: 'root',
+  providedIn: 'root'
})
export class HeroService {

```

~~カンマ消しただけです・・・。~~
原因分かる方がいらっしゃったら、コメント欄で教えていただけると幸いです。

（2020.11.15 追記）
解決しました。（やはりカンマは関係ありませんでした。）
`tsconfig`の`compilerOptions`に以下のパラメータを追加したらエラーが解消されました。

```diff:tsconfig.json
{
  "compilerOptions": {
+    "emitDecoratorMetadata": true
  },
}
```

[こちらのjest-preset-angular](https://www.npmjs.com/package/jest-preset-angular?source=post_page---------------------------#cant-resolve-all-parameters-for-someclass)によると、Angular8以上はCLIの設定によってメタデータが欠ける可能性があるそうです。

> With Angular 8 and higher, a change to the way the Angular CLI works may be causing your metadata to be lost

この設定を追加して実行すると、テストが通りました。
ちなみに、設定を変更したのに変わらない場合は、キャッシュを無効にして実行すると良いかもしれません。

```bash
$ jest hero.service --no-cache
```
（追記おわり）

---


## 環境
```bash
$ ng --version
Angular CLI: 10.1.7
Node: 12.16.1
OS: win32 x64

Angular: 10.1.6
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1001.7
@angular-devkit/build-angular   0.1002.0
@angular-devkit/core            10.1.7
@angular-devkit/schematics      10.1.7
@angular/cli                    10.1.7
@schematics/angular             10.1.7
@schematics/update              0.1001.7
rxjs                            6.6.3
typescript                      4.0.5
```

## 経緯
Angularのチュートリアル「Tour Of Heroes」の「[4. サービスの追加](https://angular.jp/tutorial/toh-pt4)」にあるサンプルコードに対してテストコードを実装しようとしていました。

テスト対象のクラスは以下。ダウンロードしたファイルそのままです。

```typescript:hero.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { MessageService } from './message.service';

@Injectable({
  providedIn: 'root',
})
export class HeroService {

  constructor(private messageService: MessageService) { }

  getHeroes(): Observable<Hero[]> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add('HeroService: fetched heroes');
    return of(HEROES);
  }
}
```

それに対して、以下のようなテストコードを実装。

```typescript:hero.service.spec.ts

import { TestBed } from '@angular/core/testing';
import { HeroService } from 'src/app/hero.service';

describe('TestHeroService', () => {
    let heroService: HeroService;

    beforeEach(() => {
        TestBed.configureTestingModule({});
        heroService = TestBed.inject(HeroService);
    });

    it('should be created', () => {
        expect(heroService).toBeTruthy();
    });
});
```

インスタンス化されることをサクッとテストして、メソッドのテストを書くつもりだったのですが、冒頭の通り

```
TypeError: Cannot read property 'ɵprov' of undefined
```

というエラーが発生しました。
調べてみると正しくDIができていないようなのですが、はっきりとした原因は分かりませんでした。

## 解決への道のり

以下のような経緯でとりあえず解決しました。

1. HeroServiceにおいて、MessageServiceをDIしないようにコメントアウトした。
2. エラーが解消したので、やはりDIが関係していると判断
2. Angular CLIを用いて別のサービス（TestService）を作成。HeroServiceと同様にMessageServiceをDIした上で同様のテストコードを作成。
3. TestServiceのテストコードが通った。
3. HeroServiceとTestServiceを比較して、`providedIn`の部分が異なることを発見し、修正したらHeroServiceのテストコードが通った。


<details><summary>修正後のコードはこちらです。</summary><div>

```typescript:hero.service.spec.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { MessageService } from './message.service';

@Injectable({
  providedIn: 'root' // カンマを消しただけ
})
export class HeroService {

  constructor(private messageService: MessageService) { }

  getHeroes(): Observable<Hero[]> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add('HeroService: fetched heroes');
    return of(HEROES);
  }
}

```

</div></details>