とんかつ時々あんどーなつ

〜たとえ低空でも飛行していられるように〜

Angular で単体テストを実行したときに出るコンソールエラーに気づく方法

はじめに

Angular で単体テストを書いているとき、テストケースは pass するがコンソールエラーが出ていることがしばしばある。

例えば次のようなエラーだ。

ERROR: 'NG0304: 'app-home-child' is not a known element (used in the 'HomeComponent' component template):
1. If 'app-home-child' is an Angular component, then verify that it is a part of an @NgModule where this component is declared.
2. If 'app-home-child' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.'

このようなエラーを解消する方法については、過去にも以下で取り上げている。

NO_ERRORS_SCHEMA を安易に使うのをやめたい話 - とんかつ時々あんどーなつ

しかし、このエラーはテスト実行時のログを見なければ確認できず、CI などでテスト結果のみを見ていると見逃してしまうこともある。

そこで今回はこのエラーを見逃さず検知する方法を紹介する。

結論

先に結論だけ書くと、単体テストの環境設定にプロパティが用意されているのでそれを有効にするとよい。 有効にすることで、このエラーがある場合にテストケース自体が失敗するようになる。

https://angular.io/api/core/testing/TestEnvironmentOptions

設定方法は Jasmine + Karma を使っているか Jest を使っているかで異なるので、順番に説明する。 ちなみにこの設定は Angular CLI v15.x で新規作成したプロジェクトではデフォルトで設定されていることも先に記しておく。

再現環境の準備

上にも書いたように v15.x で始めたプロジェクトでは最初から設定済みなのでまずは v14.x でプロジェクトを作る。

npm create @anuglar@14 ng-sample

このプロジェクトにAngular CLI で HomeComponent と HomeChildComponent を作成する。そして HomeComponent に HomeChildComponent を表示する。 これで準備はできたので、実際にエラーを確認してみる。

エラーの確認

テストを実行してみると最初に見たようなコンソールエラーが表示されている。しかし、テストケースはすべて pass していることが確認できた。 ここからは実際に事前にきづけるように TestEnvironmentOptions を設定をしていく。

TestEnvironmentOptions の設定

Jasmine + Karma の場合

テストの初期化処理が記述されている src/test.ts というファイルがある。このファイルの initTestEnvironment() の第 3 引数に TestEnvironmentOptions を渡すことができるのでそこに追加する。 追加後は以下のようになる。

// src/test.ts

...

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  { errorOnUnknownElements: true, errorOnUnknownProperties: true }
);

TestEnvironmentOptions には teardown プロパティもあるが、teardown はデフォルトで true になっているので明示的に設定はしない。 設定は以上である。これで再びテストを実行するとテストケースが失敗することが確認できる。

v15.x で新規にプロジェクトを作った場合はプロジェクト内に src/test.ts 自体が存在しない。これは @angular-devkit/build-angular の中で test.ts の設定を持つようになったためである。

Make karma main file optional by alan-agius4 · Pull Request #23957 · angular/angular-cli · GitHub

この内部で持つ設定の中で TestEnvironmentOptions が有効になっているため、v15.x で始めた場合は今回の設定が不要になる。

angular-cli/index.ts at 15.0.0 · angular/angular-cli · GitHub

あくまで v15.x で始めた場合なので、v14.x 以前のプロジェクトをアップデートして v15.x にしても適用されない。

Jest の場合

Jest で Test Environment を設定する方法は以下の jest-preset-angular のドキュメントに記載されている。

Test environment | jest-preset-angular

teardown は不要なので以下を setup-test.ts に設定する。

// setup-test.ts
globalThis.ngJest = {
  testEnvironmentOptions: {
    errorOnUnknownElements: true,
    errorOnUnknownProperties: true,
  },
};

import 'jest-preset-angular/setup-jest';

noImplicitAny が有効になっているとこの設定だけでは以下のエラーが発生する。

TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.

その場合は以下のように設定する。

import { TestEnvironmentOptions } from '@angular/core/testing';

declare global {
  var ngJest: {
    testEnvironmentOptions?: TestEnvironmentOptions;
  };
}

globalThis.ngJest = {
  testEnvironmentOptions: {
    errorOnUnknownElements: true,
    errorOnUnknownProperties: true,
  },
};

import 'jest-preset-angular/setup-jest';

おわりに

とてもニッチではあるが、個人的には困っていた内容でありスマートな解決方法もあったのでまとめてみた。 同じ悩みを持っている人に届くと嬉しい。