2018-10-02に更新

Angular2でコンポーネントのユニットテストを書いてみた

Angularのコンポーネントのユニットテストを書いてみた。
TestBedを使用しているパターン。

angular-cliでファイルを作成しつつ、
アプリケーションをある程度書いてng testしてみると大量にエラーが出るので、
それらをいくつかエラーが出ないように修正してみた。

エラーが出る原因

基本的には、htmlで使用されているコンポーネントや、
ts内で使用されているサービスなどの依存関係が満たされていないため。

アプリケーション実行時はmoduleの設定などで満たされているが、
テストは各テストで別途設定してあげなければならない。

テストは別途設定にすることで、各サービスなどはmockを使用できるようになっている。

テスト例

ユーザー情報を取得して表示するだけのページのコンポーネント例。
コンポーネント側ではActivatedRouteからidを取得し、
UserServiceでそのidからhttpでユーザー情報であるUserを取得し、
Userをコンポーネント上で表示するだけの例。

/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { ActivatedRouteStub } from '../../../../testing/router-stubs';
import { UserServiceStub } from '../../../../testing/user-service-stub';
import { UserDetailComponent } from './user-detail.component';
import { UserService } from '../../../services/user.service';
import { User } from '../../../models/user';

describe('UserDetailComponent', () => {
  let component: UserDetailComponent;
  let fixture: ComponentFixture<UserDetailComponent>;
  let activatedRoute = new ActivatedRouteStub();
  let userService = new UserServiceStub();
  let user = new User();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ UserDetailComponent ],
      providers: [
        {provide: ActivatedRoute, useValue: activatedRoute},
        {provide: UserService, useValue: userService}
      ],
    })
    .compileComponents();

    activatedRoute.testParams = {id: 1};
    userService.user = user;
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserDetailComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('user set', () => {
    expect(component.user && component.user == user).toBeTruthy();
  });
});

declarations

html上に表示するコンポーネントはここで設定。
他のコンポーネントを使っている場合はここに追記。

providers

サービスなどの設定。provideで実際のクラスを指定し、useValueでモックを指定できる。

モック

router-stubs.tsは下記で書かれたものを改造したりして使用。

Angular Docs

Observableを使用しているのでクラスにまとめた方が使いまわしやすい、ということ。
providersではそれらのモックを使用し、compileComponentでコンポーネントが構築された後、

    activatedRoute.testParams = {id: 1};
    userService.user = user;

で返すべき値をセットしている。
上記はgetメソッドになっているので、セットされるとコールバックが起動されて処理が進んでいく。
あとは自由にitで確認していくだけ。

適当にぱぱっとエラーを消して処理を追加しただけなので全体的に正しいかどうかは不明。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント