Jest测试类中的方法调用另一个方法

2lpgd968  于 2022-12-08  发布在  Jest
关注(0)|答案(1)|浏览(223)

我正在测试一个内部有方法的服务,但是对外部源的功能是模拟的。
在我的例子中,我有一个方法正在做一些处理。如果验证方法失败,它将发送一个警报(电子邮件,其他)到一个外部服务。
我想测试我的代码是否会在应该调用警报时调用警报,但我显然不希望它调用外部系统。

async Process(DateToProcess: number): Promise<void> {
    const IsWeekend: boolean = IsSaturdayOrSunday(DateToProcess);
    ...
    const DataToValidate$: Array<ResponseDTO> = await this.GetData(DateToProcess);
    const IsValid$: boolean = await this.ValidateEntries(DataToValidate$);

    if (! IsValid$) {
        await this.CreateAlert('Data is Invalid');
    }
}

我正在尝试设置测试,并具有带有存根的外部服务。

const AlertDate = new ResponseDTO();
const mockAlertService = {
    provide: AlertsService,
    useFactory: () => ({
        Create: jest.fn().mockResolvedValue(AlertData),
        Delete: jest.fn().mockResolvedValue(null),
        GetOne: jest.fn().mockResolvedValue(AlertData),
    })
}

...
const module: TestingModule = await Test.createTestingModule({
    providers: [
        ValidateService,
        mockAlertService,
    ],
}).compile();

service = module.get<ValidateDailyTimeEntriesService>(ValidateDailyTimeEntriesService);
AlertssTestService = module.get<AlertsService>(AlertsService);

这个设置是有效的,我可以模拟返回值。我还包含了其他服务,我在这里删除了这些服务,它们使用相同的格式并加载基本的测试数据,我可以验证这些数据是否有效。
但是,我的测试无法验证是否调用了要创建的警报。

it('should send an alert if there are no times entries and it is not a weekend', async () => {
    const spyProcess_: jest.SpyInstance = jest.spyOn(service, 'Process');
    const spyGetData_: jest.SpyInstance = jest.spyOn(service, 'GetData').mockResolvedValue(TestData);

    const spyValidateData_: jest.SpyInstance = jest.spyOn(service, 'ValidateData');
    const spyCreateAlert_: jest.SpyInstance = jest.spyOn(service, 'CreateAlert').mockResolvedValue(true);

    await service.Process(20221012); // Call the main function
    expect(spyProcess_).toHaveBeenCalled(); // These 2 calls work, were called in the this test
    expect(spyProcess_).toHaveBeenCalledWith(20221012); 

    expect(spyGetData_).toHaveBeenCalled(); // Works, this was called
    expect(spyGetData_).toHaveReturnedWith(TestData);

    expect(spyValidateData_).toHaveBeenCalled(); // This fails???
    expect(spyCreateAlert_).toHaveBeenCalled(); // This will fail as well

    spyCreateAlert_.mockClear();
    spyValidateData_.mockClear();
    spyGetData_.mockClear();
    spyProcessOneDate_.mockClear();
});

错误表明,最后两个间谍将不会工作,即使他们在我看来是相同的风格作为那些做。

expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0

    > 298 |             expect(spyValidateData_).toHaveBeenCalled();

    > 298 |             expect(spyCreateAlert_).toHaveBeenCalled();

EDIT它与异步/等待与承诺处理有关。如果我这样做:

async Process(): Promise<void> {
    this.GetData(DateToProcess).then( (DataToValidate$: Array<ResponseDTO>) => {});
    this.CreateAlert('Data is Invalid').then( (Result$: boolean) => {});
    return;
}

测试将通过。但是,使用await将失败:

async Process(): Promise<void> {
    const DataToValidate$: Array<ResponseDTO> = await this.GetData(DateToProcess);
    const Result$: boolean = await this.CreateAlert();
    return;
}
gfttwv5a

gfttwv5a1#

我的问题与我正在进行的处理有关。await/async不能在有回调的循环中运行,如forEach()。使用for.. of格式将更正我遇到的错误。它需要对我编写的代码进行一些重构,但它确实更正了问题。
我的简单示例没有显示辅助函数中的循环。因此,简单的重写将是:

const DataToValidate$: Array<ResponseDTO> = await this.GetData(DateToProcess);
    DataToValidate$.forEach( (OneRecord: ResponseDTO) => {
        const IsValid$: boolean = await this.ValidateEntries(OneRecord);
    }

但是,VS代码指示在等待之前需要异步

const DataToValidate$: Array<ResponseDTO> = await this.GetData(DateToProcess);
    DataToValidate$.forEach(async (OneRecord: ResponseDTO) => {
        const IsValid$: boolean = await this.ValidateEntries(OneRecord);
    }

但是,由于forEach()是回调样式循环,因此forEach()中的async不起作用。

const DataToValidate$: Array<ResponseDTO> = await this.GetData(DateToProcess);
    for (OneRecord of DataToValidate$) {
        const IsValid$: boolean = await this.ValidateEntries(OneRecord);
    }

这将允许正确的处理。

相关问题