如何在 Sinon 中存根具有多个参数的猫鼬方法?
How to stub mongoose methods with multiple arguments in Sinon?
我在 Node.js 中使用 Mongoose,这是我的 DAO 方法。
function findPostsByCategoryId(categoryId, first, second) {
var sortingOrd = { 'createdAt': -1 };
return Post.find({ 'categoryId': categoryId }).sort(sortingOrd).skip(first).limit(second);
}
现在,我想在我的测试用例中使用 Sinon 存根这样的方法。
describe('findPostsByCategoryId', function () {
it('should find post by category id', function () {
var stub = sinon.stub(Post, 'find');
stub.callsFake(() => {
return Promise.resolve(posts);
});
postDao.findPostsByCategoryId(1, 2, 3).then(response => {
assert.length(response, 1);
})
.catch((error) => {
assert.isDefined(error);
});
});
});
这给我返回一个错误
TypeError: Post.find(...).sort is not a function.
您能否阐明如何对链接有多个函数的 DAO 方法进行存根?
要对这样链接的函数进行单元测试,只需链接 stub
和 spy
实例并验证它们是否使用预期值调用:
it('should find post by category id', function () {
const limitSpy = sinon.spy();
const skipStub = sinon.stub().returns({ limit: limitSpy });
const sortStub = sinon.stub().returns({ skip: skipStub });
const findStub = sinon.stub(Post, 'find').returns({ sort: sortStub });
postDao.findPostsByCategoryId(1, 2, 3);
sinon.assert.calledWithExactly(findStub, { 'categoryId': 1 }); // SUCCESS
sinon.assert.calledWithExactly(sortStub, { 'createdAt': -1 }); // SUCCESS
sinon.assert.calledWithExactly(skipStub, 2); // SUCCESS
sinon.assert.calledWithExactly(limitSpy, 3); // SUCCESS
});
单元测试解决方案如下:
dao.js
:
const Post = require("./models/post");
function findPostsByCategoryId(categoryId, first, second) {
var sortingOrd = { createdAt: -1 };
return Post.find({ categoryId: categoryId })
.sort(sortingOrd)
.skip(first)
.limit(second);
}
module.exports = {
findPostsByCategoryId,
};
./models/post.js
:
// simulate Post model
const Post = {
find(where) {
return this;
},
sort(...args) {
return this;
},
skip(...args) {
return this;
},
limit(n) {},
};
module.exports = Post;
dao.test.js
:
const dao = require("./dao");
const Post = require("./models/post");
const sinon = require("sinon");
const { expect } = require("chai");
describe("Name of the group", () => {
afterEach(() => {
sinon.restore();
});
it("should pass", () => {
sinon.stub(Post);
Post.find.returnsThis();
Post.sort.returnsThis();
Post.skip.returnsThis();
const mResponse = { rowCount: 100 };
Post.limit.resolves(mResponse);
return dao.findPostsByCategoryId(1, 2, 3).then((response) => {
expect(response).to.be.eql(mResponse);
sinon.assert.calledWithExactly(Post.find, { categoryId: 1 });
sinon.assert.calledWithExactly(Post.sort, { createdAt: -1 });
sinon.assert.calledWithExactly(Post.skip, 2);
sinon.assert.calledWithExactly(Post.limit, 3);
});
});
});
包含覆盖率报告的单元测试结果:
54920719
✓ should pass
1 passing (14ms)
-----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files | 89.66 | 100 | 55.56 | 89.66 | |
54920719 | 100 | 100 | 100 | 100 | |
dao.js | 100 | 100 | 100 | 100 | |
dao.test.js | 100 | 100 | 100 | 100 | |
54920719/models | 40 | 100 | 0 | 40 | |
post.js | 40 | 100 | 0 | 40 | 4,7,10 |
-----------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/Whosebug/54920719
我在 Node.js 中使用 Mongoose,这是我的 DAO 方法。
function findPostsByCategoryId(categoryId, first, second) {
var sortingOrd = { 'createdAt': -1 };
return Post.find({ 'categoryId': categoryId }).sort(sortingOrd).skip(first).limit(second);
}
现在,我想在我的测试用例中使用 Sinon 存根这样的方法。
describe('findPostsByCategoryId', function () {
it('should find post by category id', function () {
var stub = sinon.stub(Post, 'find');
stub.callsFake(() => {
return Promise.resolve(posts);
});
postDao.findPostsByCategoryId(1, 2, 3).then(response => {
assert.length(response, 1);
})
.catch((error) => {
assert.isDefined(error);
});
});
});
这给我返回一个错误
TypeError: Post.find(...).sort is not a function.
您能否阐明如何对链接有多个函数的 DAO 方法进行存根?
要对这样链接的函数进行单元测试,只需链接 stub
和 spy
实例并验证它们是否使用预期值调用:
it('should find post by category id', function () {
const limitSpy = sinon.spy();
const skipStub = sinon.stub().returns({ limit: limitSpy });
const sortStub = sinon.stub().returns({ skip: skipStub });
const findStub = sinon.stub(Post, 'find').returns({ sort: sortStub });
postDao.findPostsByCategoryId(1, 2, 3);
sinon.assert.calledWithExactly(findStub, { 'categoryId': 1 }); // SUCCESS
sinon.assert.calledWithExactly(sortStub, { 'createdAt': -1 }); // SUCCESS
sinon.assert.calledWithExactly(skipStub, 2); // SUCCESS
sinon.assert.calledWithExactly(limitSpy, 3); // SUCCESS
});
单元测试解决方案如下:
dao.js
:
const Post = require("./models/post");
function findPostsByCategoryId(categoryId, first, second) {
var sortingOrd = { createdAt: -1 };
return Post.find({ categoryId: categoryId })
.sort(sortingOrd)
.skip(first)
.limit(second);
}
module.exports = {
findPostsByCategoryId,
};
./models/post.js
:
// simulate Post model
const Post = {
find(where) {
return this;
},
sort(...args) {
return this;
},
skip(...args) {
return this;
},
limit(n) {},
};
module.exports = Post;
dao.test.js
:
const dao = require("./dao");
const Post = require("./models/post");
const sinon = require("sinon");
const { expect } = require("chai");
describe("Name of the group", () => {
afterEach(() => {
sinon.restore();
});
it("should pass", () => {
sinon.stub(Post);
Post.find.returnsThis();
Post.sort.returnsThis();
Post.skip.returnsThis();
const mResponse = { rowCount: 100 };
Post.limit.resolves(mResponse);
return dao.findPostsByCategoryId(1, 2, 3).then((response) => {
expect(response).to.be.eql(mResponse);
sinon.assert.calledWithExactly(Post.find, { categoryId: 1 });
sinon.assert.calledWithExactly(Post.sort, { createdAt: -1 });
sinon.assert.calledWithExactly(Post.skip, 2);
sinon.assert.calledWithExactly(Post.limit, 3);
});
});
});
包含覆盖率报告的单元测试结果:
54920719
✓ should pass
1 passing (14ms)
-----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files | 89.66 | 100 | 55.56 | 89.66 | |
54920719 | 100 | 100 | 100 | 100 | |
dao.js | 100 | 100 | 100 | 100 | |
dao.test.js | 100 | 100 | 100 | 100 | |
54920719/models | 40 | 100 | 0 | 40 | |
post.js | 40 | 100 | 0 | 40 | 4,7,10 |
-----------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/Whosebug/54920719