Here is the function under test:
export const callStoredProcedure = async (procedureName, procedureArgs)
=> {
let resultSet: any;
try {
await knexClient.transaction(async trx => {
await trx.raw(`CALL ${procedureName}(${procedureArgs});`).then(result => {
if (result[0] && result[0][0]) {
resultSet = JSON.stringify(result[0][0]);
}
});
});
} catch (err) {
console.log(err);
}
return resultSet;
};
And here I'm mocking the knexClient in a beforeEach block:
let knexClientMock;
beforeEach(() => {
// Stub Data source clients
const rawStub = sinon.stub().resolves([{ affectiveRows: 0, insertId: 0 }]);
knexClientMock = sinon.stub(knexClient, 'transaction').callsFake(
async (): Promise<any> => {
return {
raw: rawStub,
};
},
);
});
However, when I run my tests the if statement if (result[0] && result[0][0])
never runs and Jest coverage shows everything is uncovered from the raw
statement down to the catch
.
The mocking seems to be working correctly in that it uses the mock knexClient.transaction
, but it leaves the rest of the lines uncovered. I think I just want to mock the raw
function with a mock promise result and allow the .then
function to run.
How can I mock the knexClient.transaction.raw
function only and allow the rest of the code to have test coverage?
The issue is that your test stubs do not correctly mock the objects being used:
The "transaction" method in your code takes a single argument (a callback function) and invokes this callback, passing it a transaction executor that has an asynchronous "raw" method.
Your test stubs make the "transaction" method return an object that has an async raw method.
When writing unit tests for your code, it is very important to understand how your code works, first. Otherwise it is extremely easy to write meaningless tests that won't protect against introducing bugs.