web-dev-qa-db-ja.com

単体テストで材料コンポーネントをKarmaと連携させる方法Angular

angular CLIプロジェクトがセットアップされています。 <md-card>のようなangularマテリアルコンポーネントを使用するフォームを作成しました。

angular docs の手順に従って、最初のKarma/Jasmine単体テストを書くところから始めました。

これは私のコンポーネントテンプレートです。

<md-card [ngClass]="'dialog-card'">
<md-card-title [ngClass]="'dialog-title'">
    {{title}}
</md-card-title>
<md-card-content>

    <form (ngSubmit)="login()" #loginForm="ngForm">

        <md-input-container class="md-block">
            <input md-input [(ngModel)]="user.email" 
                name="userEmail" type="email" placeholder="Email" 
                ngControl="userEmail" 
            required>
        </md-input-container>
        <br>

        <md-input-container class="md-block">
            <input md-input [(ngModel)]="user.password" 
                name="userPassword" type="password" placeholder="Password" 
                ngControl="userPassword" 
            required>
        </md-input-container>
        <br>

        <tm-message msgText="Wrong username or password" *ngIf="showError"></tm-message>
        <br>


        <button md-button type="submit" [disabled]="!loginForm.form.valid">Login</button>

        <p (click)="openForgotPasswordModal()">Forgot Password?</p>

    </form>

</md-card-content>

これは私のカルマの仕様です:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';
import { MaterialModule, MdDialogRef, MdDialog  } from '@angular/material';
import { FormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';

import { TmLoginComponent } from './tm-login.component';
import { TmMessageComponent } from '../../shared/components/tm-message.component';
import { UserAuthenticationService } from '../login/user-authentication.service';

describe('TmLoginComponent (inline template)', () => {

let comp: TmLoginComponent;
let fixture: ComponentFixture < TmLoginComponent > ;
let de: DebugElement;
let el: HTMLElement;

beforeEach(() => {
    TestBed.configureTestingModule({
        declarations: [TmLoginComponent, TmMessageComponent], // declare the test component
        imports: [MaterialModule, FormsModule,
            RouterTestingModule.withRoutes(
                [{
                    path: 'login',
                    component: TmLoginComponent
                }, ])
        ],
        providers: [UserAuthenticationService],

    });

    fixture = TestBed.createComponent(TmLoginComponent);

    comp = fixture.componentInstance; // TmLoginComponent test instance

    // query for the title <h1> by CSS element selector
    de = fixture.debugElement.query(By.css('.title'));
    el = de.nativeElement;
});

    it('should display original title', () => {
        fixture.detectChanges();
        expect(el.textContent).toContain(comp.title);
    });
});

この時点で、タイトルが適切に表示されていることを確認する基本的な単体テストを実行しようとしています。

ただし、マテリアル固有のエラーが多数発生しています。いいね

MdDialogのプロバイダーはありません。

リンクをクリックするとmdダイアログが開きます。コードは(かなり長い).tsファイルにありますが、ここでは問題ではありません。

テストベッドのどこにMdDialogを追加しますか?プロバイダーに追加すると、「オーバーレイのプロバイダーがありません」というエラーが表示されます。私はそれを修正する方法がわかりません。

開始時にすべての材料コンポーネントを含めるようにカルマを構成する方法はありますか?

ありがとう。

19
Snowman

すべてのプロバイダーは、モジュールでforRoot()を呼び出すことにより提供されます

imports: [ MaterialModule.forRoot() ]

バージョンの場合2.0.0-beta.4以降(forRootメソッドが削除されたため):

imports: [ MaterialModule ]

バージョンの場合2.0.0-beta.11以降、MaterialModuleが削除されたため、テストケースに必要なモジュールを自分でインポートする必要があります。

imports: [ MatButtonModule, MatDialogModule ]
4
Paul Samsotha

現在の手法では、Angular Material Modules、MaterialModuleは非推奨であり、 2.0.0-beta.11で削除されました

import {
    MatButtonModule,
    MatIconModule
} from '@angular/material';

次に、TestBed構成のインポートと同じリストを追加します。

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [ ... ],
        imports: [
            MatButtonModule,
            MatIconModule,
            ...
        ],
        providers: [ ... ]
    })
        .compileComponents();
}));
10
isherwood

今日もこれに苦労していますが、ジャスミンのプロバイダーを使用して、必要なクラスを自分でモックアウトする必要があります。面倒ですし、もっと良い方法があればいいのですが、少なくともエラーはもうありません...

誰もがより良いアイデアを持っている場合は、コミュニティの残りの部分を啓発してください!

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AlertDialogComponent } from './alert-dialog.component';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';

describe('AlertDialogComponent', () => {
  let component: AlertDialogComponent;
  let fixture: ComponentFixture<AlertDialogComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [MatDialogModule],
      declarations: [AlertDialogComponent],
      providers: [
        {
          provide: MatDialogRef, useValue: {}
        },
        {
          provide: MAT_DIALOG_DATA, useValue:{}
        }
     ],
    }).compileComponents();
  }));
1
Peter