Sinon.js 带参数的间谍函数
Spy function with params by Sinon.js
我正在尝试编写一些使用 typeorm 的代码的单元测试,而无需访问数据库。
我正在为 spy/stub/mock 使用 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 文档,似乎 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;
});
});
欢迎任何帮助。提前致谢!
我看到了你的代码,有一些地方可以改进:
- 用
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;
});
});
希望对您有所帮助
我正在尝试编写一些使用 typeorm 的代码的单元测试,而无需访问数据库。 我正在为 spy/stub/mock 使用 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 文档,似乎 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;
});
});
欢迎任何帮助。提前致谢!
我看到了你的代码,有一些地方可以改进:
- 用
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;
});
});
希望对您有所帮助