如何使材料组件在单元测试Angular中与Karma一起工作



我设置了一个角度 CLI 项目。我制作了一个使用角度材料组件的表单,例如<md-card>

刚刚开始编写我的第一个 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?如果我将其添加到提供程序,则会收到错误:"没有覆盖提供程序"。我不知道如何解决这个问题。

有什么方法可以将业力配置为在开始时包含所有材料组件?

谢谢。

当前的技术需要单独导入 Angular Material 模块,因为MaterialModule模块已被弃用并在 2.0.0-beta.11 中删除:

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

然后在 TestBed 配置中添加与导入相同的列表:

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

所有提供程序都是通过在模块上调用forRoot()来提供的

imports: [ MaterialModule.forRoot() ]

对于 2.0.0-beta.4 及更高版本(因为 forRoot 方法已被删除):

imports: [ MaterialModule ]

对于 2.0.0-beta.11 及更高版本,由于已删除MaterialModule,因此您必须自己导入测试用例所需的模块:

imports: [ MatButtonModule, MatDialogModule ]

我今天也一直在为此苦苦挣扎,您需要通过使用 Jasmine 中的提供程序自己模拟必要的类。这很麻烦,我希望有更好的方法,但至少没有更多的错误......

如果有人有更好的想法,请启发社区的其他人!

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();
  }));

相关内容

  • 没有找到相关文章