Reputation: 17564
I am trying to test a function called multiQuery
and to make sure that it calls another function query
with the correct parameters and the correct number of times.
Following is a simplification of the code I am using. This is the object I use to create the object:
const createDb = () => {
const query = (sql, values, type = "all") => {
console.log(`original query called: ${sql}, ${values}, ${type}`);
return Promise.resolve();
};
const multiQuery = requests => Promise.all(
requests.map( req => query(req.sql, req.values, req.mode || "all") )
);
return {
query,
multiQuery
};
};
And here is the test:
const sinon = require("sinon");
const chai = require("chai");
const expect = chai.expect;
const sinonChai = require("sinon-chai");
chai.use(sinonChai);
describe("multiQuery", () => {
it("should call query multiple times with the correct parameters", async() => {
const requests = [
{ sql: "hello", values: [1, 2, 3], mode: "first" },
{ sql: "world", values: [4, 5, 6], mode: "all" },
{ sql: "moon", values: [7, 8] }
];
const db = createDb();
const spy = sinon.spy( db, "query" );
await db.multiQuery( requests );
expect( spy ).to.have.been.calledThrice();
expect( spy ).to.have.been.calledWith( "hello", [1, 2, 3], "first" );
});
});
Problem is that no matter what I do, I always get the message:
AssertionError: expected query to have been called exactly thrice, but it was called 0 times
And I can't get to fix it.
This happens because multiQuery
is bound to the original function instead of the spy.
I was thinking of perhaps injecting the query
dependency in multiQuery
, but then I don't want to be passing a dependency every time I call it, nor do I want to pollute the object's API with unneeded factory methods.
I really have no idea on how to solve this here.... How can I fix this?
Upvotes: 1
Views: 596
Reputation: 950
You are correct as to why the test is failing.
You need to make multiQuery reference the same query
as what is returned, by putting query
on an object:
A potential solution:
const createDb = () => {
const db = { //the name here isn't important
query,
multiQuery
};
const query = (sql, values, type = "all") => {
console.log(`original query called: ${sql}, ${values}, ${type}`);
return Promise.resolve();
};
const multiQuery = requests => Promise.all(
requests.map( req => db.query(req.sql, req.values, req.mode || "all") )
);
return db;
};
Upvotes: 1
Reputation: 17564
After asking around and making more tests, I have found that if I change the createDb
function to the following:
const createDb = () => {
const db = {}
db.query = (sql, values, type = "all") => {
console.log(`original query called: ${sql}, ${values}, ${type}`);
return Promise.resolve();
};
db.multiQuery = requests => Promise.all(
requests.map( req => db.query(req.sql, req.values, req.mode || "all") )
);
return db;
}
The spy method in sinon will work as expected.
Upvotes: 1