我是角度开发的新手,也是使用茉莉花进行单元测试的新手。 我创建了一个组件,使用角度材料MatDialogRef,来自@ angular / material的MAT_DIALOG_DATA播放对话框。 该组件工作正常,但单元测试给我一个我无法解决的错误。
我真的需要这个工作,任何帮助将不胜感激.... 在此先感谢.. !!!
请在下面找到我的代码:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';
import 'hammerjs';
import { NgxPhoneSelectModule } from 'ngx-phone-select';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatInputModule, MatButtonModule, MatSelectModule } from '@angular/material';
import { MatGridListModule } from '@angular/material';
import { MatTableModule } from '@angular/material';
import { MatDialogModule} from '@angular/material';
import { MatCardModule} from '@angular/material';
import { MaterialModule } from './modules/material/material.module';
import { AppComponent } from './app.component';
import { CustomerComponent } from './components/customer/customer.component';
import { LoginComponent } from './components/login/login.component';
import { ForgetPasswordComponent } from './components/forget-password/forget-password.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { LoaderService } from './services/loader.service';
import { CustomerDataService } from './services/customer-data.service';
import { UserService } from './services/user/user.service';
import { HeaderComponent } from './components/header/header.component';
import { UpdateCustomerComponent } from './components/update-customer/update-customer.component';
import { AuthService } from './services/auth.service';
import { AuthGuard } from './services/auth/auth.guard';
import { DeleteCustomerComponent } from './components/delete-customer/delete-customer.component';
import { FooterComponent } from './components/footer/footer.component';
const appRoutes: Routes = [
{
path: '',
component: LoginComponent
},
{
path: 'create-customer',
component: CustomerComponent,
// canActivate: [AuthGuard] // ristrict direct access of links
},
{
path: 'forget-password',
component: ForgetPasswordComponent,
// canActivate: [AuthGuard] // ristrict direct access of links
},
{
path: 'dashboard',
component: DashboardComponent,
// canActivate: [AuthGuard] // ristrict direct access of links
},
{
path: 'update-customer',
component: UpdateCustomerComponent,
// canActivate: [AuthGuard] // ristrict direct access of links
},
{
path: '**',
component: PageNotFoundComponent
}
];
@NgModule({
declarations: [
AppComponent,
CustomerComponent,
LoginComponent,
ForgetPasswordComponent,
PageNotFoundComponent,
DashboardComponent,
HeaderComponent,
UpdateCustomerComponent,
DeleteCustomerComponent,
FooterComponent
],
imports: [
BrowserModule,
HttpClientModule,
HttpModule,
RouterModule.forRoot(appRoutes),
NgxPhoneSelectModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
MatInputModule,
MatButtonModule,
MatSelectModule,
MatGridListModule,
MatTableModule,
MaterialModule
],
entryComponents: [
DeleteCustomerComponent
],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
providers: [LoaderService, AuthService, AuthGuard, UserService, CustomerDataService],
bootstrap: [AppComponent]
})
export class AppModule { }
删除客户组件
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Router} from '@angular/router';
@Component({
selector: 'app-delete-customer',
templateUrl: './delete-customer.component.html',
styleUrls: ['./delete-customer.component.scss']
})
export class DeleteCustomerComponent implements OnInit {
constructor(private router: Router, public deleteCustDialogRef: MatDialogRef<DeleteCustomerComponent>, @Inject(MAT_DIALOG_DATA) public data: string) { }
ngOnInit() {
}
onClosedeleteCustomer() {
this.deleteCustDialogRef.close('confirm');
this.router.navigate(['./dashboard']);
}
onCloseCancel() {
this.deleteCustDialogRef.close('cancel');
}
}
删除-customer.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {RouterTestingModule} from '@angular/router/testing';
import { DeleteCustomerComponent } from './delete-customer.component';
import { MaterialModule } from '../../modules/material/material.module';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog, MatDialogModule } from '@angular/material';
describe('DeleteCustomerComponent', () => {
let component: DeleteCustomerComponent;
let fixture: ComponentFixture<DeleteCustomerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DeleteCustomerComponent ],
imports: [ MaterialModule, RouterTestingModule, MatDialogModule ],
providers : [ MatDialogRef, MAT_DIALOG_DATA, MatDialog ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DeleteCustomerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
业力错误
DeleteCustomerComponent should create
Failed: Can't resolve all parameters for MatDialogRef: (?, ?, ?).
Error: Can't resolve all parameters for MatDialogRef: (?, ?, ?).
at syntaxError (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:485:22)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15662:1)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getTypeMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15497:1)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getInjectableMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15477:1)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver.getProviderMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15837:1)
at http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15748:1
at Array.forEach (<anonymous>)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver._getProvidersMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15708:1)
at CompileMetadataResolver.webpackJsonp.../../../compiler/esm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler.js:15276:1)
at JitCompiler.webpackJsonp.../../../compiler/esm5/compiler.js.JitCompiler._loadModules (http://localhost:9876/_karma_webpack_/webpack:/C:/dewatering_FST/node_modules/@angular/compiler/esm5/compiler
答案 0 :(得分:9)
当我尝试测试对话框组件时,我遇到了同样的问题。我的解决方案基于角度材料源代码中的dialog test。
import { MyDialogComponent } from './mydialog.component';
import { async, TestBed, inject } from '@angular/core/testing';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatDialog } from '@angular/material/dialog';
import { OverlayContainer } from '@angular/cdk/overlay';
describe('MyDialogComponent', () => {
let dialog: MatDialog;
let overlayContainer: OverlayContainer;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyDialogComponent],
imports: [
MatDialogModule,
]
});
TestBed.overrideModule(BrowserDynamicTestingModule, {
set: {
entryComponents: [MyDialogComponent]
}
});
TestBed.compileComponents();
}));
beforeEach(inject([MatDialog, OverlayContainer],
(d: MatDialog, oc: OverlayContainer) => {
dialog = d;
overlayContainer = oc;
})
);
afterEach(() => {
overlayContainer.ngOnDestroy();
});
it('should open a dialog with a component', () => {
const dialogRef = dialog.open(MyDialogComponent, {
data: { param: '1' }
});
// verify
expect(dialogRef.componentInstance instanceof MyDialogComponent).toBe(true);
});
});
我不确定这是正确的方法,但我自己还是初学者。
答案 1 :(得分:7)
根据您的需要,更简单的方法是注入一个模拟MatDialog提供程序,该提供程序具有用于close或open方法的jasmine间谍。例如:
import { MyDialogComponent } from './mydialog.component';
import { async, TestBed, inject } from '@angular/core/testing';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { MatDialog } from '@angular/material/dialog';
describe('MyDialogComponent', () => {
const mockDialogRef = {
close: jasmine.createSpy('close')
};
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyDialogComponent],
imports: [MatDialogModule],
providers: [
{
provide: MatDialogRef,
useValue: mockDialogRef
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AddOrUpdateModuleBundleDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('#onClosedeleteCustomer should close the dialog', () => {
component.onClosedeleteCustomer();
expect(mockDialogRef.close).toHaveBeenCalled();
});
});
这个要点是,不要在测试中注入MatDialog或MatDialogRef的实例。使用茉莉花间谍注入模拟对象,可以告诉您是否已调用方法。
答案 2 :(得分:0)
我已将MatDialogRef
添加到模块中的提供程序
@NgModule({
declarations: [
AppComponent,
.
.
other components...
.
.
],
imports: [
BrowserModule,
],
providers: [
{
provide: MatDialogRef
}
],
bootstrap: [AppComponent]
})
export class AppModule { }