【问题标题】:Jest: Test recursive call inside Promise笑话:在 Promise 中测试递归调用
【发布时间】:2019-01-25 17:36:53
【问题描述】:

我在测试以下课程时遇到了一些问题。

interface Connector {
   connect: () => Promise<void>;
}

class Unit {
   private connector: Connector;

   constructor(connector: Connector) {
      this.connector = connector;
   }

   public attemptConnect(iteration: number, max: number): void {
      console.log("attempt" + iteration);

      this.connector.connect()
         .then(() => {
            console.log("connected");
         })
         .catch((error) => {
            if (iteration < max) {
               this.attemptConnect(iteration + 1, max);
            }
         });
   }
}

我想测试 Connector.connect() 函数被调用的次数是否正确。 我正在尝试通过以下方式实现这一目标:

describe("Unit", () => {
   it("fails to record more than one recursion", async () => {
      const connector: Connector = {
         connect: jest.fn().mockRejectedValue(new Error("foo")),
      };
      const unit: Unit = new Unit(connector);

      await unit.attemptConnect(1, 4);

      expect((connector.connect as jest.Mock).mock.calls.length).toBe(4);
   });
});

不幸的是,expect() 调用失败了,说

Error: expect(received).toBe(expected) // Object.is equality

Expected: 4
Received: 1

如果我使用调试器并观察值

(connector.connect as jest.Mock).mock.calls.length

我可以看到通话被正确记录。只有当测试完成时数字是错误的。

感谢您的帮助!

【问题讨论】:

    标签: typescript unit-testing mocking jestjs


    【解决方案1】:

    解决方案 1

    返回attemptConnect()中的promise:

    public attemptConnect(iteration: number, max: number): Promise<void> {
      console.log("attempt" + iteration);
    
      return this.connector.connect()
        .then(() => {
          console.log("connected");
        })
        .catch((error) => {
          if (iteration < max) {
            return this.attemptConnect(iteration + 1, max);
          }
        });
    }
    

    解决方案 2

    await 用于测试中所需的事件循环周期数:

    describe("Unit", () => {
      it("fails to record more than one recursion", async () => {
        const connector: Connector = {
          connect: jest.fn().mockRejectedValue(new Error("foo")),
        };
        const unit: Unit = new Unit(connector);
    
        unit.attemptConnect(1, 4);
    
        // await enough event loop cycles for all the callbacks queued
        // by then() and catch() to run, in this case 5:
        await Promise.resolve().then().then().then().then();
    
        expect((connector.connect as jest.Mock).mock.calls.length).toBe(4);
      });
    });
    

    详情

    测试等待attemptConnect(),但由于它没有返回任何内容,因此await 没有任何内容,同步测试继续执行。 expect()then()catch() 排队的回调有机会运行之前运行并失败。

    【讨论】:

    • 非常感谢。如果未返回承诺,是否还有可行的解决方案?
    • @Treecj 是的,我将其添加到我的答案中
    猜你喜欢
    • 2021-04-25
    • 2018-10-19
    • 1970-01-01
    • 2019-09-30
    • 2017-12-03
    • 1970-01-01
    • 2018-08-09
    • 2019-09-06
    • 1970-01-01
    相关资源
    最近更新 更多