【发布时间】:2022-01-13 19:43:55
【问题描述】:
我正在尝试对我编写的服务进行单元测试。大多数测试都通过了,但我的最后一个测试失败了,尽管我的模拟设置与我的一个工作测试相同。
这是我的服务。您会注意到我导入了其他服务来进行 API 调用并创建一个快餐栏。同样在我的服务中,我有逻辑来确定应该调用哪个 API:
showMarkOffline(incident: any): void {
let name;
let apiCall;
if (incident.sessionType === 'network') {
name = incident.networkName;
const nodes = (incident.nodes || []).map((node) => node.id);
apiCall = () => this.hubsApiService.markOffline(incident.id, nodes);
} else {
name = (incident && incident.workerName) ? incident.workerName : incident.id;
const gatewayId = (incident && incident.gatewayId) ? incident.gatewayId : null;
apiCall = this.phonesApiService.markOffLine(gatewayId, incident.id);
}
const dialogRef = this.modalWrapperService.openConfirmDialog('ns.common:markOfflineDialog.title',
['ns.common:markOfflineDialog.content', { 0: name }],
'ns.common:markOfflineDialog.ok',
'ns.common:cancel');
dialogRef.afterClosed().subscribe((confirmation: boolean) => {
if (confirmation) {
apiCall().subscribe(() => {
// the second test doesn't seem to get here
this.snackbarWrapperService
.openSuccess('ns.common:markOfflineDialog.passed', { 0: name });
}, () => {
this.snackbarWrapperService
.openError('ns.common:markOfflineDialog.failed', { 0: name });
});
}
});
}
这很好用,现在我需要编写单元测试:
describe('IncidentsService', () => {
let service: IncidentsService;
const mockHubsApiService = {
markOffline: jest.fn()
};
const mockPhonesApiService = {
markOffLine: jest.fn()
};
const mockModalDialogWrapperService = {
openConfirmDialog: jest.fn()
};
const mockSnackBarWrapperService = {
openSuccess: jest.fn(),
openError: jest.fn()
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [{
provide: HubsApiService,
useValue: mockHubsApiService
}, {
provide: PhonesApiService,
useValue: mockPhonesApiService
}, {
provide: ModalDialogWrapperService,
useValue: mockModalDialogWrapperService
}, {
provide: SnackBarWrapperService,
useValue: mockSnackBarWrapperService
}]
});
service = TestBed.inject(IncidentsService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('showMarkOffline', () => {
// this test passes!!!!
it('should call hubsApiService.markOffline, openConfirmDialog and openSuccess', () => {
const incident = {
id: '12345',
sessionType: 'network',
networkName: 'RaduNetwork',
nodes: [{ id: '1', foo: 'bar' }, { id: '2', foo: 'bar' }, { id: '3', foo: 'bar' }, { id: '4', foo: 'bar' }]
};
const modalSpy = spyOn(service.modalWrapperService, 'openConfirmDialog').and
.returnValue({ afterClosed: () => of(true) });
const apiSpy = spyOn(service.hubsApiService, 'markOffline').and
.returnValue(of(true));
const snackBarSpy = spyOn(service.snackbarWrapperService, 'openSuccess');
service.showMarkOffline(incident);
expect(modalSpy).toHaveBeenCalledWith('ns.common:markOfflineDialog.title',
['ns.common:markOfflineDialog.content', { 0: 'RaduNetwork' }],
'ns.common:markOfflineDialog.ok',
'ns.common:cancel');
expect(apiSpy).toHaveBeenCalledWith('12345', ['1', '2', '3', '4']);
expect(snackBarSpy).toHaveBeenCalledWith('ns.common:markOfflineDialog.passed', { 0: 'RaduNetwork' });
});
// this test fails!
it('should call phonesApiService.markOffline, openConfirmDialog and openSuccess',() => {
const incident = {
id: '12345',
workerName: 'workerName',
gatewayId: '54321',
sessionType: 'whatever'
};
const modalSpy = spyOn(service.modalWrapperService, 'openConfirmDialog').and
.returnValue({ afterClosed: () => of(true) });
const apiSpy = spyOn(service.phonesApiService, 'markOffLine').and
.returnValue(of(true));;
const snackBarSpy = spyOn(service.snackbarWrapperService, 'openSuccess');
service.showMarkOffline(incident);
expect(modalSpy).toHaveBeenCalledWith('ns.common:markOfflineDialog.title',
['ns.common:markOfflineDialog.content', { 0: 'workerName' }],
'ns.common:markOfflineDialog.ok',
'ns.common:cancel');
expect(apiSpy).toHaveBeenCalledWith('54321', '12345');
// below is the failing test
expect(snackBarSpy).toHaveBeenCalledWith('ns.common:markOfflineDialog.passed', { 0: 'workerName' });
});
});
});
如您所见,我正在为 API 服务调用设置间谍,并且正在为 API 调用设置返回值。问题在于第二个测试,模拟的服务/间谍确实被调用,但.subscribe 方法似乎没有被执行,因此在第二个测试中我的代码从未进入apiCall().subscribe 回调(请参阅中的注释服务)并且测试在这里失败:
expect(snackBarSpy).toHaveBeenCalledWith('ns.common:markOfflineDialog.passed', { 0: 'workerName' });
出现错误:
Error: expect(spy).toHaveBeenCalledWith(...expected)
Expected: "ns.common:markOfflineDialog.passed", {"0": "workerName"}
Number of calls: 0
我不确定为什么这适用于第一个测试而不是第二个。我尝试过使用ngOnDestroy,我尝试过更改我的间谍和模拟的设置,但似乎没有任何东西可以解决第二个单元测试。
【问题讨论】:
标签: angular unit-testing jestjs