I'm trying to write some unit tests of code that uses typeorm without hitting the DB. And I'm using sinon for spy/stub/mock. This is my function.
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();
}
I already wrote a fake test to make sure execute()
is called by using spy function.
But I want to test the params of these functions createQueryBuilder
..., the sure the params are correct.
I took a look at sinon document and it seems like sinon support test params by this API: spy().withArgs(arg1, arg2...)
.
But I'm not sure how to spy my function correctly.
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;
});
});
Any help is welcome. Thanks in advance!
I saw your code and there's something can be improved:
returnsThis()
to replace return fakeManager
await
when calling 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;
});
});
Hope it helps