1

我们有一些使用 Aurelia 框架和 Dialog 插件的 TypeScript 代码,我们正在尝试使用 Jasmine 进行测试,但无法弄清楚如何正确执行。

这是源函数:

openDialog(action: string) {
    this._dialogService.open({ viewModel: AddAccountWizard })
        .whenClosed(result => {
            if (!result.wasCancelled && result.output) {
                const step = this.steps.find((i) => i.action === action);
                if (step) {
                    step.isCompleted = true;
                }
            }
        });
}

我们可以创建一个 DialogService 间谍,并轻松验证 open 方法 - 但我们无法弄清楚如何让间谍使用模拟结果参数调用 whenClosed 方法,以便我们可以断言该步骤已完成。

这是当前的 Jasmine 代码:

it("opens a dialog when clicking on incomplete bank account", async done => {
    // arrange
    arrangeMemberVerificationStatus();
    await component.create(bootstrap);
    const vm = component.viewModel as GettingStartedCustomElement;
    dialogService.open.and.callFake(() => {
        return { whenClosed: () => Promise.resolve({})};
    });

    // act
    $(".link, .-arrow")[0].click();

    // assert
    expect(dialogService.open).toHaveBeenCalledWith({ viewModel: AddAccountWizard });
    expect(vm.steps[2].isCompleted).toBeTruthy(); // FAILS

    done();
});
4

1 回答 1

1

我们最近刚刚更新了我们的 DialogService 并遇到了同样的问题,所以我们制作了这个到目前为止适合我们目的的原始模拟。它相当有限,不能很好地模拟具有不同结果的多个调用,但应该适用于您的上述情况:

export class DialogServiceMock {
    shouldCancelDialog = false;
    leaveDialogOpen = false;
    desiredOutput = {};
    open = () => {
        let result = { wasCancelled: this.shouldCancelDialog, output: this.desiredOutput };
        let closedPromise = this.leaveDialogOpen ? new Promise((r) => { }) : Promise.resolve(result);
        let resultPromise = Promise.resolve({ closeResult: closedPromise });
        resultPromise.whenClosed = (callback) => {
            return this.leaveDialogOpen ? new Promise((r) => { }) : Promise.resolve(typeof callback == "function" ? callback(result) : null);
        };
        return resultPromise;
    };
}

这个模拟可以配置为测试各种响应,当用户取消对话框时,以及对话框仍然打开的场景。

我们还没有完成 e2e 测试,所以我不知道有什么好的方法可以确保你等到 .click() 调用完成,这样你的 expect() 和 whenClosed 之间就没有竞争条件() 逻辑,但我认为您应该能够像这样在测试中使用模拟:

it("opens a dialog when clicking on incomplete bank account", async done => {
    // arrange
    arrangeMemberVerificationStatus();
    await component.create(bootstrap);
    const vm = component.viewModel as GettingStartedCustomElement;

    let mockDialogService = new MockDialogService();
    vm.dialogService = mockDialogService; //Or however you're injecting the mock into the constructor; I don't see the code where you're doing that right now.
    spyOn(mockDialogService, 'open').and.callThrough();

    // act
    $(".link, .-arrow")[0].click();
    browser.sleep(100)//I'm guessing there's a better way to verify that it's finished with e2e testing, but the point is to make sure it finishes before we assert.

    // assert
    expect(mockDialogService.open).toHaveBeenCalledWith({ viewModel: AddAccountWizard });
    expect(vm.steps[2].isCompleted).toBeTruthy(); // FAILS

    done();
});
于 2018-04-11T15:02:34.530 回答