
Angularでテストコードを書いてみたいんだけど、情報が少なくてよく分からないんだよね。。
具体的なソースコード付きで教えてもらえると嬉しいな。
こんな悩みを解決します。
- 本記事の内容
- Angularの単体テストについて
- 単体テストの書き方について
- 具体的なソースコード
- 本記事の執筆者


- 元エンジニア(歴7年)、資格保有数約20個(IT系以外も含む)
- 物販月利50万円⇒脱サラ
- 物販、システム開発、アフィリエイト、プログラミング、投資をやっています。
- 物販は彼女と楽しみながらやっています!
今回は、Angular×Jasmineでテストコードを書く方法を解説します。
僕自身、本記事の内容を業務で実践してきたので、Angularの単体テストを書く際に役立つこと間違いなしです。
本記事を読めば、Angular×Jasmineの基礎的な知識が身に付きますよ!



サラッと読み終わるので、是非最後まで読んでみてください!
Angularのテストとは
Angularのテストは主に2つあります。
- 単体テスト(Jasmine+Karma)
- e2eテスト(protractor or Cypress)
単体テスト(Jasmine+Karma)
AngularにはデフォルトでJasmineとKarmaがインストールされています。
テストを実行することで、「spec.ts」ファイルのテストがすべて実行されます。
e2eテスト(protractor or Cypress)
Angularにはデフォルトで「protractor」がインストールされています。
テストを実行することで、e2eフォルダ内のテストがすべて実行されます。



e2eテストについては今回割愛しますね。
単体テスト実行方法
ng test
上記コマンドを実行します。


↑が実行結果になります。



全てSUCCESSであればOKです!
特定のファイルだけテストを実行したい場合
fdescribe('SampleComponent', () => {
});
describeの先頭に「f」を付与することで、fを付与したdescribe内のテストのみが実行されます。
非常に便利ですが、fを付与した状態でコミットしないように注意してください。
ソースコード解説
では早速、ソースコードの解説をしていきますね。



僕が業務で気になったコードをまとめているので、是非参考にしてみてください。
TestBed
主要なAngularテストユーティリティの1つです。
使用例
TestBed.configureTestingModule({
});
CUSTOM_ELEMENTS_SCHEMA
コンポーネントのテストでは、依存関係にあるコンポーネントをテスト内で定義しないと、未知の要素と判断されてエラーになります。
この時に発生するコンソールエラーを回避するために「CUSTOM_ELEMENTS_SCHEMA」を使用します。
使用例
TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
});
describe
テストのグループです。
describe内でdescribeを定義することも可能です。
使用例
describe('テストのグループ', () => {
});
beforeEach
主に初期化処理を行います。
使用例
beforeEach(() => {
});
detectChanges
change Detectionが行われたことを伝えます。
change Detectionとは、モデルの変更を検知しUIに反映することです。
使用例
beforeEach(() => {
fixture.detectChanges();
});
expectの種類
expect(component).toBeTruthy();
上記のように、expectを使用してテストを検証します。
Matcherには種類があるので、適切なものを使用します。
項目 | 説明 | 備考 |
---|---|---|
toBe | 同一かどうか | ※厳密等価演算子を使って比較 |
toEqual | 同一オブジェクトかどうか | |
toContain | 期待値が含まれるかどうか | |
toBeTruthy | Trueかどうか | |
toBeFalsy | Falseかどうか | |
toBeNull | Nullかどうか | |
toBeNaN | NaNかどうか | |
toBeLessThan | 実効値が期待値より大きいかどうか | |
toBeGreaterThan | 実効値が期待値より小さいかどうか | |
toBeDefined | undefinedではない | |
toBeUndefined | undefinedである | |
toHaveBeenCalled | 関数が実行されたかどうか | |
toHaveBeenCalledWith | 関数が実行されたかどうか | ※引数チェックも含む |
toThrow | 例外が発生するかどうか |
否定する場合
expect(xxx).not.ToEqual(yyy)
否定する場合は、「not」を付ければOKです。
各テストの書き方
component
主に、取得したデータが正しく表示されているかを確認します。



HTMLにベタ書きされている文言等はテストしなくてもOKです。
あまりやる意味もないですし。。
const hogeServiceSpy = jasmine.createSpyObj('HogeService', ['getHoge']);
beforeEach(
TestBed.configureTestingModule({
declarations: [SampleComponent],
providers: [
{ provide: HogeService, useValue: hogeServiceSpy },
],
}).compileComponents();
hogeServiceSpy.getHoge.and.returnValue(of(getHoge()));
);
取得するデータはspyを使用し、モックから取得するようにします。
spyを使用することで、コンポーネントのテストに集中することができます。
describe('getHoge', () => {
it('hoge情報取得', () => {
const mock = getHoge();
const debugElement = fixture.debugElement;
expect(debugElement.query(By.css('.id')).nativeElement.textContent).toEqual(mock.id);
});
});
function getHoge() {
return {
id: 1,
};
}
あとは、HTMLに表示されている内容と実際のモックデータを比較してテストします。
directive
import { HogeDirective } from './hoge.directive';
describe('HogeDirective', () => {
it('onClick時', () => {
const directive = new HogeDirective();
directive.onClick();
expect(hoge).toHaveBeenCalled();
});
});
特に特殊なことはなく、ディレクティブのインスタンスを生成し、各処理をテストするだけです。
pipe
import { HogePipe } from './hoge.pipe';
describe('HogePipe', () => {
const pipe = new HogePipe();
it('transform', () => {
expect(pipe.transform('abc')).toBe('abc');
});
});
pipeはtransformを使うので、上記のようにテストします。
その他
@Inputのテスト
子コンポーネントの場合、Inputで値を受け取る場合が多いです。
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-hoge-test',
templateUrl: './hoge-test.component.html',
styleUrls: ['./hoge-test.component.scss']
})
export class HogeTestComponent implements OnInit {
@Input() title: string;
}
上記のようにコンポーネントが定義されているとします。
it('titleのテスト', () => {
component.title = 'タイトル';
fixture.detectChanges();
const element = fixture.debugElement.query(By.css('.title')).nativeElement as HTMLSpanElement;
expect(element.textContent).toBe('タイトル');
});
↑がテストコードになります。
変数に値を入れた後、detectChangesを忘れないようしてください。
前提条件にクエリパラメータを使う場合
画面によっては、クエリパラメータが付与されていることが前提の場合もあります。
そういった場合は、providersで定義します。
describe('HogeComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{
provide: ActivatedRoute,
useValue: {
snapshot: {
paramMap: convertToParamMap({ id: 123 })
}
}
}
]
});
}));
});
ルーティングのテスト
ルーティングのテストは、ルーティング処理実行後のURLを見て判断します。
redirect() {
this.router.navigate(['/hoge']);
}
↑のようにserviceのメソッドが定義されているとします。
let router: Router;
let service: HogeService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppRoutingModule],
providers: [HogeService],
});
router = TestBed.inject(Router);
service = TestBed.inject(HogeService);
});
it('リダイレクトしていること', fakeAsync(() => {
service.redirect();
tick();
expect(router.url).toBe('/hoge');
}));
↑がテストコードです。
メソッドが実行されたか確認したい場合
メソッドが実行されたかどうかを確認したい場合は、「toHaveBeenCalled」「toHaveBeenCalledWith」を使用します。
a() {
b();
}
例えば、コンポーネントに↑のようなメソッドがあるとします。
component.a();
expect(component.b).toHaveBeenCalled();
テストコードは↑のようになります。
まとめ
今回は、Angular×Jasmineでテストコードを書く方法を解説しました。
Angularのテストって情報が少なくて困りますよね。。
ではまた!
- おすすめ本はこちら!



僕は↑の本でAngularの勉強をしました!
非常に分かりやすいのでおすすめです!
- 自由な生き方がしたいなら!
自由な生き方をするためには、稼ぐスキルを身に付けなければなりません。
当サイト「リバトレ」では稼ぐスキルに関する情報を日々発信しているので、興味のあるものから見て頂ければ嬉しいです。
コメント