【问题标题】:Spy function with params by Sinon.jsSinon.js 的带有参数的间谍功能
【发布时间】:2020-07-21 17:08:31
【问题描述】:

我正在尝试编写一些使用 typeorm 的代码单元测试,而不会影响数据库。 我正在使用 sinon 进行间谍/存根/模拟。 这是我的功能。

  async updateDoingToFailedWithLock(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.manager
      .getRepository(Report)
      .createQueryBuilder("report")
      .useTransaction(true)
      .setLock("pessimistic_write")
      .update(Report)
      .set({ status: ReportStatus.FAILED })
      .where(`(status = "doing")`)
      .execute();
  }

我已经写了一个假测试来确保execute()被使用spy函数调用。 但我想测试这些函数createQueryBuilder...的参数,确保参数正确。 我查看了 sinon 文档,似乎 sinon 通过这个 API 支持测试参数:spy().withArgs(arg1, arg2...)

但我不确定如何正确监视我的函数。

describe("updateDoingToFailedWithLock()", (): void => {
    let sandbox: Sinon.SinonSandbox;

    beforeEach(() => (sandbox = Sinon.createSandbox()));
    afterEach(() => sandbox.restore);

    it("should be success", async (): Promise<void> => {
      const fakeManager = {
        getRepository: () => {
          return fakeManager;
        },
        createQueryBuilder: () => {
          return fakeManager;
        },
        useTransaction: () => {
          return fakeManager;
        },
        setLock: () => {
          return fakeManager;
        },
        update: () => {
          return fakeManager;
        },
        set: () => {
          return fakeManager;
        },
        where: () => {
          return fakeManager;
        },
        execute: () => {},
      };
      const fakeQueryRunner = {
        manager: fakeManager,
      };
      const connection = new typeorm.Connection({ type: "mysql" });
      const reportService = new ReportService();
      sandbox.stub(connection, "createQueryRunner").callsFake((): any => {
        return fakeQueryRunner;
      });

      const queryRunner = connection.createQueryRunner();
      const spy = sandbox.spy(fakeManager, "execute");

      reportService.updateDoingToFailedWithLock(queryRunner);
      expect(spy.calledOnce).be.true;
    });
  });

欢迎任何帮助。提前致谢!

【问题讨论】:

    标签: node.js unit-testing mocking sinon typeorm


    【解决方案1】:

    我看到了你的代码,还有一些可以改进的地方:

    • 使用returnsThis() 替换return fakeManager
    • 拨打updateDoingToFailedWithLock时不要忘记await
    describe("updateDoingToFailedWithLock()", (): void => {
      let sandbox: sinon.SinonSandbox;
    
      beforeEach(() => (sandbox = sinon.createSandbox()));
      afterEach(() => sandbox.restore);
    
      it("should be success", async (): Promise<void> => {
    
        // using returnsThis()
        const fakeManager = {
          getRepository: sandbox.stub().returnsThis(),
          createQueryBuilder: sandbox.stub().returnsThis(),
          useTransaction: sandbox.stub().returnsThis(),
          setLock: sandbox.stub().returnsThis(),
          update: sandbox.stub().returnsThis(),
          set: sandbox.stub().returnsThis(),
          where: sandbox.stub().returnsThis(),
          execute: sandbox.stub().returnsThis(),      
        }
    
        const fakeQueryRunner = {
          manager: fakeManager,
        };
    
        const reportService = new ReportService();
    
        // having await here is important
        await reportService.updateDoingToFailedWithLock(fakeQueryRunner);
    
    
        expect(fakeManager.execute.calledOnce).to.be.true;
        expect(fakeManager.createQueryBuilder.calledWith('report')).to.be.true;
      });
    });
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回答。看起来不错,但是当我运行测试时,我遇到了这个问题:TypeError: queryRunner.manager.getRepository(...).createQueryBuilder(...).useTransaction(...).setLock(...).update(...).set(...).where(...).andWhere is not a function
    • 似乎您添加了andWhere,这在问题的代码示例中不存在。为了解决这个错误,我们可以在where之后添加andWhere: sandbox.stub().returnsThis()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2018-12-26
    • 2020-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多