【发布时间】:2022-11-10 14:50:05
【问题描述】:
我正在尝试为我的服务编写一个测试,并且一切正常(服务,到目前为止的测试),但我无法验证调用了一个函数,这失败了。但是,测试的代码覆盖率输出表明该行正在执行,如果我自己运行代码,它确实会删除数据。
我试图仅复制服务处理的相关部分来说明我的问题。我的服务维护来自外部服务的假期日期。这将删除错误条目,并每年添加新的假期日期记录。我已将其缩减为我遇到问题的功能。
export class UpdateService {
constructor(
private readonly HolidayDateDataService_: HolidayDatesService,
) {
this.RemoveInvalidHolidayDateEntriesForAYear(Year);
}
async RemoveInvalidHolidayDateEntriesForAYear(Year: number): Promise<void> {
let ExistingHolidayDates: Array<HolidayDatesResponseDTO>;
try {
ExistingHolidayDates = await this.HolidayDateDataService_.GetAllRecordsByYear(Year); // From external API
} catch (Exception) {
return;
}
ExistingHolidayDates.forEach( async (OneDateEntry: HolidayDatesResponseDTO) => {
const HolidayIdIsActive: boolean = await this.ValidateHolidayIdActive_(OneDateEntry.HolidayId); // Validates Entry should be maintained.
if (! HolidayIdIsActive) {
await this.DeleteOneHolidayDateRecord_(OneDateEntry);
}
});
return;
}
async DeleteOneHolidayDateRecord_(HolidayDateData: HolidayDatesResponseDTO): Promise<void> {
console.log('Start DeleteOneHolidayDateRecord_');
try {
console.log('Start HolidayDateDataService');
await this.HolidayDateDataService_.Delete(
new HolidayDatesEntity(HolidayDateData.HolidayId, HolidayDateData.Name, HolidayDateData.Year),
HolidayDateData.Key_
);
console.log('End HolidayDateDataService');
} catch (Exception) {
; // Do nothing, try the next one
}
console.log('End DeleteOneHolidayDateRecord_');
return;
}
async ValidateHolidayIdActive_(HolidayId: string): Promise<boolean> {
console.log('Start ValidateHolidayIdActive_');
try {
console.log('Start HolidayIdDateService');
const HolidayIdData: HolidayIdsResponseDTO = await this.HolidayIdDataService_.GetOne(HolidayId);
console.log('End HolidayIdDateService');
if (HolidayIdData && HolidayIdData.Active) {
return true;
}
} catch (Exception) {
; // Do nothing as the method ends with a return false
}
console.log('End ValidateHolidayIdActive_');
return false;
}
}
正如我所说,所有这些都有效。但是,我正在尝试测试并验证是否调用了删除。
describe('UpdateService', () => {
let service: UpdateService;
let HolidayIdsTestService: HolidayIdsService;
let HolidayDatesTestService: HolidayDatesService;
const HolidayRecords: Array<HolidaysApi> = new Array<HolidaysApi>(
{ id: 31, name: 'Christmas Day', observedDate: '2022-12-27' } as HolidaysApi,
{ id: 32, name: 'Boxing Day', observedDate: '2022-12-28' } as HolidaysApi,
);
beforeEach(async () => {
const mockHolidayIdsService = {
provide: HolidayIdsService,
useValue: {
GetOne: jest.fn(),
},
};
const mockHolidayDatesService = {
provide: HolidayDatesService,
useFactory: () => ({
Delete: jest.fn(),
GetAllRecordsByYear: jest.fn(),
}),
};
const module: TestingModule = await Test.createTestingModule({
providers: [
UpdateService,
mockHolidayDatesService,
mockHolidayIdsService,
],
}).compile();
service = module.get<UpdateService>(UpdateService);
HolidayIdsTestService = module.get<HolidayIdsService>(HolidayIdsService);
HolidayDatesTestService = module.get<HolidayDatesService>(HolidayDatesService);
});
it('should delete HolidayDate records if ValidateHolidayIdActive_ returns false', async () => {
jest.spyOn(HolidayDatesTestService, GetAllRecordsByYear').mockResolvedValue(HolidayDateRecords);
jest.spyOn(HolidayIdsTestService, 'GetOne').mockResolvedValue(new HolidayIdsResponseDTO('Fake_Holiday_Id', false, 31, 'Christmas Day'));
jest.spyOn(HolidayDatesTestService, 'Delete').mockResolvedValue();
await service.RemoveInvalidHolidayDateEntriesForAYear(2022);
expect(HolidayIdsTestService.GetOne).toHaveBeenCalledTimes(2);
expect(HolidayDatesTestService.Delete).toHaveBeenCalledTimes(2);
});
我的测试中的问题是最后一个期望失败:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
532 | await service.RemoveInvalidHolidayDateEntriesForAYear(2022);
533 | expect(HolidayIdsTestService.GetOne).toHaveBeenCalledTimes(2);
> 534 | expect(HolidayDatesTestService.Delete).toHaveBeenCalledTimes(2);
| ^
我遇到的问题是 ValidateHolidayIdActive_ 被调用了 2 次(它在内部使用 HoldiayIdsTestService,这是被模拟的),这是我所期望的,并且因为它被模拟返回 False 状态,所以 DeleteOneHolidayDateRecord_ 应该被调用 2 次也是。但是,在调用验证内部服务时,.toHaveBeenCalled() 和 .toHaveBeenCalledTimes(2) 都失败了,这又被模拟了。
但是,通过代码中的 console.log() 调用,我可以看到模块以正确的顺序调用,一切都开始了,然后完成了整个链。
记录#1
console.log Start ValidateHolidayIdActive_
console.log Start HolidayIdDateService
console.log Start ValidateHolidayIdActive_
console.log Start HolidayIdDateService
console.log End HolidayIdDateService
console.log End ValidateHolidayIdActive_
console.log End HolidayIdDateService
console.log End ValidateHolidayIdActive_
记录#2
console.log Start DeleteOneHolidayDateRecord_
console.log Start HolidayDateDataService
console.log Start DeleteOneHolidayDateRecord_
console.log Start HolidayDateDataService
console.log End HolidayDateDataService
console.log End DeleteOneHolidayDateRecord_
console.log End HolidayDateDataService
console.log End DeleteOneHolidayDateRecord_
它似乎确实可以正确调用并完成。但是,一个功能被监视为正常工作,而另一个则没有。我无法理解我的错误。
感谢您提供任何帮助,因为它应该是一个简单的错误,但完全让我感到沮丧,而且我似乎找不到它。我最初在一个函数中拥有更多的功能,并且像这样分解它来测试每个函数(它适用于相同风格的模拟)。
【问题讨论】:
标签: typescript jestjs nestjs