Sinon.spy 不适用于简单对象
Sinon.spy not working on simple object
背景
我正在尝试测试一个名为 multiQuery
的函数,并确保它使用正确的参数和正确的次数调用另一个函数 query
。
代码
以下是我使用的代码的简化版。这是我用来创建对象的对象:
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
};
};
这是测试:
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" );
});
});
问题
问题是无论我做什么,我总是收到消息:
AssertionError: expected query to have been called exactly thrice, but
it was called 0 times
而且我无法修复它。
发生这种情况是因为 multiQuery
绑定到原始函数而不是间谍。
集思广益
我想也许在 multiQuery
中注入 query
依赖项,但是我不想每次调用它时都传递依赖项,也不想污染对象的 API 具有不需要的工厂方法。
我真的不知道如何解决这个问题....
我该如何解决这个问题?
关于测试失败的原因,您是正确的。
您需要通过将 query
放在对象上,使 multiQuery 引用与返回的相同 query
:
可能的解决方案:
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;
};
四处询问并进行更多测试后,我发现如果将 createDb
函数更改为以下内容:
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;
}
sinon 中的 spy 方法将按预期工作。
背景
我正在尝试测试一个名为 multiQuery
的函数,并确保它使用正确的参数和正确的次数调用另一个函数 query
。
代码
以下是我使用的代码的简化版。这是我用来创建对象的对象:
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
};
};
这是测试:
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" );
});
});
问题
问题是无论我做什么,我总是收到消息:
AssertionError: expected query to have been called exactly thrice, but it was called 0 times
而且我无法修复它。
发生这种情况是因为 multiQuery
绑定到原始函数而不是间谍。
集思广益
我想也许在 multiQuery
中注入 query
依赖项,但是我不想每次调用它时都传递依赖项,也不想污染对象的 API 具有不需要的工厂方法。
我真的不知道如何解决这个问题.... 我该如何解决这个问题?
关于测试失败的原因,您是正确的。
您需要通过将 query
放在对象上,使 multiQuery 引用与返回的相同 query
:
可能的解决方案:
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;
};
四处询问并进行更多测试后,我发现如果将 createDb
函数更改为以下内容:
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;
}
sinon 中的 spy 方法将按预期工作。