0

我正在为一个对话框组件编写测试,该组件处理调用函数时手动提示的 PWA 安装事件。然后它将解决从BeforeInstallPromptEvent.userChoice属性返回的承诺。

但是,当我尝试测试此功能时,我从 jasmine 收到错误消息:

'userChoice.then 不是函数'

我理解这一点,因为我尝试使用 spyOn 对其进行监视,然后检查结果。

我用 Promises 尝试了其他一些事情,因为 userChoice 返回了一个已解决的承诺(https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent),但到目前为止没有任何效果。

这是我要测试的功能。BeforeInstallPromptEvent存储在 installEvent 对象中,该对象从 传递到组件,app.ts然后存储在数据中。

this.data.installEvent.userChoice
            .then((choiceResult) => {
                if (choiceResult.outcome === 'accepted') {
                    doSomething();

在我的测试规范中,我使用以下内容创建了一个 mockData 对象:

const mockData = {
  installEvent: {
    prompt: () => {},
    userChoice: Promise.resolve().then(() => {
      return { choiceResult: { outcome: "accepted" } };
    }),
  },
};

到目前为止,我的测试规范(经过多次不同的尝试)是这样的:

it("should do something after user accepted", fakeAsync(() => {
 mockData.installEvent.userChoice.then((result) => {
      return result.choiceResult.outcome;
//this test returns true
      expect(result.choiceResult.outcome).toEqual("accepted");
    }); 
flush();
//but the function gets never called
expect(component.doSomething).toHaveBeenCalled();
});

或者使用产生错误的spyOn函数:userChoice

it("should do something after user accepted", () => {
spyOn(mockData.installEvent, "userChoice").and.returnValue("accepted");

expect(mockData.installEvent.userChoice).toBe("accepted)
expect(component.doSomething).toHaveBeenCalled();
});

有了这个,我设法已经测试了该data.installEvent.prompt函数是否被调用。

但我不知道如何测试userChoicePromise 解析为“已接受”,然后触发 if 条件。

请帮我。由于我是一个关于测试(在 Angular 中)的初学者,因此很高兴能够解释测试此类 Promises 背后的方法。

非常感谢您!

4

2 回答 2

1

非常感谢@AliF50 的回答!我尝试了方法 1,除了后来发现的一个小错误外,它确实有效:

const mockData = {
  installEvent: {
    prompt: () => {},
    userChoice: Promise.resolve({ choiceResult: { outcome: "accepted" } }),
  },
};

需要是

const mockData = {
  installEvent: {
    prompt: () => {},
    userChoice: Promise.resolve( { outcome: "accepted" } ),
  },
};

因为该beforeinstallprompt.userChoice属性的结构提供了一个具有关键结果的对象,如 if 所示:

if (choiceResult.outcome === "accepted")

因此,在我们的示例中,当解决测试规范中的承诺时,结果等于 if 条件中的选择结果。

更改后,现在一切正常!

于 2020-10-30T13:59:44.960 回答
1

问题是你已经解决了承诺,mockData而间谍没有返回承诺。

方法一

const mockData = {
  installEvent: {
    prompt: () => {},
    userChoice: Promise.resolve({ choiceResult: { outcome: "accepted" } }),
  },
};
it("should do something after user accepted", fakeAsync(() => {
 mockData.installEvent.userChoice.then((result) => {
      // return result.choiceResult.outcome;, remove return here and only test the assertion
//this test returns true
      expect(result.choiceResult.outcome).toEqual("accepted");
      expect(component.doSomething).toHaveBeenCalled(); // make sure doSomething gets called
    }); 
flush(); // flush the promises
});

方法2(不能做)

it("should do something after user accepted", () => {
  // you can't spy on userChoice since you can only spy on methods/functions and not variables
  spyOn(mockData.installEvent, "userChoice").and.returnValue("accepted");

  expect(mockData.installEvent.userChoice).toBe("accepted)
  expect(component.doSomething).toHaveBeenCalled();
});

方法 2 无法完成,因为您只能使用spyOn方法和函数,而不能使用属性。

于 2020-10-30T12:48:52.147 回答