我对Angular Material单元测试和Service单元测试还比较陌生。我为应用程序创建了一个服务,通过该服务,我可以调用Material SnackBar打开函数并传递消息参数。需要时,它在每个组件上都可以正常工作,但是对其进行单元测试对我来说太可怕了。
import { Injectable } from '@angular/core';
import { MatSnackBar, MatSnackBarRef, MatSnackBarConfig } from '@angular/material/snack-bar';
@Injectable({
providedIn: 'root',
})
export class NotificationService {
private snackBarConfig: MatSnackBarConfig;
private snackBarRef: MatSnackBarRef<any>;
private snackBarAutoHide = '5000';
constructor(private sb: MatSnackBar) {}
openSnackBar(message) {
this.snackBarConfig = new MatSnackBarConfig();
this.snackBarConfig.duration = parseInt(this.snackBarAutoHide, 0);
this.sb.open(message, 'Dismiss', this.snackBarConfig);
}
}
并且所谓的测试规范文件是这个:
import { Overlay } from '@angular/cdk/overlay';
import { TestBed } from '@angular/core/testing';
import { MatSnackBar } from '@angular/material/snack-bar';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { NotificationService } from './notification-service';
describe('NotificationService testing:', () => {
let spectator: SpectatorService<NotificationService>;
const createService = createServiceFactory({
service: NotificationService,
providers: [MatSnackBar, Overlay],
entryComponents: [],
mocks: [NotificationService],
});
beforeEach(() => (spectator = createService()));
it('should openSnackBar() be known as function', () => {
expect(typeof spectator.service.openSnackBar).toEqual('function');
});
it('should be created', () => {
const dateService = spectator.inject(NotificationService);
spyOn(spectator.service, 'openSnackBar');
dateService.openSnackBar('Test');
expect(spectator.service.openSnackBar).toHaveBeenCalledWith('Test');
});
});
我的问题如下:
谢谢你。
好吧,我在朋友的帮助下解决了这个问题。第一个问题是在构造函数中定义的是私有版本,而不是SnackBar的公共版本(private sb: MatSnackBar
-> public sb: MatSnackBar
)。其次,我对测试文件进行了一些修改,现在看起来像这样并且可以正常工作:
import { Overlay } from '@angular/cdk/overlay';
import { TestBed } from '@angular/core/testing';
import { MatSnackBar, MatSnackBarModule, MatSnackBarConfig } from '@angular/material/snack-bar';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { NotificationService } from './notification-service';
describe('NotificationService testing:', () => {
let spectator: SpectatorService<NotificationService>;
let snackBar: MatSnackBar;
let snackBarConfig: MatSnackBarConfig;
const createService = createServiceFactory({
service: NotificationService,
imports: [MatSnackBarModule],
providers: [MatSnackBarModule, Overlay],
entryComponents: [],
mocks: [NotificationService],
});
beforeEach(() => {
TestBed.configureTestingModule({});
snackBar = TestBed.inject(MatSnackBar);
spectator = createService();
});
it('should service be created', () => {
const service: NotificationService = TestBed.inject(NotificationService);
expect(service).toBeTruthy();
});
it('should openSnackBar() be known as function', () => {
expect(typeof spectator.service.openSnackBar).toEqual('function');
});
it(`should openSnackBar() call SnackBar's own open()`, () => {
const service: NotificationService = TestBed.inject(NotificationService);
snackBarConfig = new MatSnackBarConfig();
snackBarConfig.duration = parseInt('5000', 0);
const serviceSpy = spyOn(service, 'openSnackBar').and.callThrough();
const snackSpy = spyOn(snackBar, 'open');
expect(serviceSpy).not.toHaveBeenCalled();
expect(snackSpy).not.toHaveBeenCalled();
service.openSnackBar('Hello');
expect(serviceSpy).toHaveBeenCalledWith('Hello');
expect(snackSpy).toHaveBeenCalledWith('Hello', 'Dismiss', snackBarConfig);
});
});
希望将来有人遇到同样的问题时,它会有所帮助。另外,我敢肯定,有一种更好,更好的方法可以做到这一点,但现在它正在起作用,并提供100%的覆盖率,这很重要。但将来会对此表示欢迎。