Шпионская функция с параметрами от Синона. js - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь написать несколько модульных тестов кода, который использует 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() вызывается с помощью функции шпиона. Но я хочу проверить параметры этих функций createQueryBuilder ..., уверен, что параметры правильные. Я взглянул на документ sinon, и похоже, что параметры API поддержки 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;
    });
  });

Любая помощь приветствуется. Заранее спасибо!

1 Ответ

1 голос
/ 13 апреля 2020

Я видел ваш код, и есть что-то, что можно улучшить:

  • Используйте returnsThis() для замены return fakeManager
  • Не забывайте await при вызове updateDoingToFailedWithLock
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;
  });
});

Надеюсь, это поможет

...