如何正确测试 return Mongoose 查询为 Promises 的函数
How to properly test functions that return Mongoose queries as Promises
我正在尝试编写一个基本单元测试来处理下面的函数,但无法让它运行。我如何测试是否返回了正确的 npm-express 响应之类的东西?
我已经看过 , https://codeutopia.net/blog/2016/06/10/mongoose-models-and-unit-tests-the-definitive-guide/, and Unit Test with Mongoose,但还是想不通。我目前的最佳猜测和由此产生的错误低于要测试的功能。如果可能的话,除了 Mocha、Sinon 和 Chai.expect(即不是 sinon-mongoose、chai-as-expected 等),我不想使用任何东西。欢迎任何其他建议,比如我 can/should 在这里测试的其他建议。谢谢!
待测函数:
function testGetOneProfile(user_id, res) {
Profiles
.findOne(user_id)
.exec()
.then( (profile) => {
let name = profile.user_name,
skills = profile.skills.join('\n'),
data = { 'name': name, 'skills': skills };
return res
.status(200)
.send(data);
})
.catch( (err) => console.log('Error:', err));
}
我目前的最佳猜测单元测试:
const mongoose = require('mongoose'),
sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect,
Profile = require('../models/profileModel'),
foo = require('../bin/foo');
mongoose.Promise = global.Promise;
describe('testGetOneProfile', function() {
beforeEach( function() {
sinon.stub(Profile, 'findOne');
});
afterEach( function() {
Profile.findOne.restore();
});
it('should send a response', function() {
let mock_user_id = 'U5YEHNYBS';
let expectedModel = {
user_id: 'U5YEHNYBS',
user_name: 'gus',
skills: [ 'JavaScript', 'Node.js', 'Java', 'Fitness', 'Riding', 'backend']
};
let expectedResponse = {
'name': 'gus',
'skills': 'JavaScript, Node.js, Java, Fitness, Riding, backend'
};
let res = {
send: sinon.stub(),
status: sinon.stub()
};
sinon.stub(mongoose.Query.prototype, 'exec').yields(null, expectedResponse);
Profile.findOne.returns(expectedModel);
foo.testGetOneProfile(mock_user_id, res);
sinon.assert.calledWith(res.send, expectedResponse);
});
});
测试留言:
1) testGetOneProfile should send a response:
TypeError: Profiles.findOne(...).exec is not a function
at Object.testGetOneProfile (bin\foo.js:187:10)
at Context.<anonymous> (test\foo.test.js:99:12)
这是一个有点棘手的场景。这里的问题是测试中的 findOne 存根 return 是模型对象 - 相反,它需要 return 一个包含 属性 exec
的对象,而后者又是最终解析为模型值的 promise-returning 函数...是的,如前所述,它有点棘手 :)
像这样:
const findOneResult = {
exec: sinon.stub().resolves(expectedModel)
}
Profile.findOne.returns(findOneResult);
您还需要在响应对象上具有 status
函数 return 包含 send
函数的对象
//if we set up the stub to return the res object
//it returns the necessary func
res.status.returns(res);
我认为您不需要更改测试中的任何其他内容,它可能会像那样工作。请注意,您使用 sinon 2.0 或更新版本才能在存根上存在 resolves 函数(或者您可以将 sinon-as-promised 与 sinon 1.x)
一起使用
这篇 post 更详细地介绍了如何处理这样的复杂对象:
https://codeutopia.net/blog/2016/05/23/sinon-js-quick-tip-how-to-stubmock-complex-objects-such-as-dom-objects/
我正在尝试编写一个基本单元测试来处理下面的函数,但无法让它运行。我如何测试是否返回了正确的 npm-express 响应之类的东西?
我已经看过
待测函数:
function testGetOneProfile(user_id, res) {
Profiles
.findOne(user_id)
.exec()
.then( (profile) => {
let name = profile.user_name,
skills = profile.skills.join('\n'),
data = { 'name': name, 'skills': skills };
return res
.status(200)
.send(data);
})
.catch( (err) => console.log('Error:', err));
}
我目前的最佳猜测单元测试:
const mongoose = require('mongoose'),
sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect,
Profile = require('../models/profileModel'),
foo = require('../bin/foo');
mongoose.Promise = global.Promise;
describe('testGetOneProfile', function() {
beforeEach( function() {
sinon.stub(Profile, 'findOne');
});
afterEach( function() {
Profile.findOne.restore();
});
it('should send a response', function() {
let mock_user_id = 'U5YEHNYBS';
let expectedModel = {
user_id: 'U5YEHNYBS',
user_name: 'gus',
skills: [ 'JavaScript', 'Node.js', 'Java', 'Fitness', 'Riding', 'backend']
};
let expectedResponse = {
'name': 'gus',
'skills': 'JavaScript, Node.js, Java, Fitness, Riding, backend'
};
let res = {
send: sinon.stub(),
status: sinon.stub()
};
sinon.stub(mongoose.Query.prototype, 'exec').yields(null, expectedResponse);
Profile.findOne.returns(expectedModel);
foo.testGetOneProfile(mock_user_id, res);
sinon.assert.calledWith(res.send, expectedResponse);
});
});
测试留言:
1) testGetOneProfile should send a response:
TypeError: Profiles.findOne(...).exec is not a function
at Object.testGetOneProfile (bin\foo.js:187:10)
at Context.<anonymous> (test\foo.test.js:99:12)
这是一个有点棘手的场景。这里的问题是测试中的 findOne 存根 return 是模型对象 - 相反,它需要 return 一个包含 属性 exec
的对象,而后者又是最终解析为模型值的 promise-returning 函数...是的,如前所述,它有点棘手 :)
像这样:
const findOneResult = {
exec: sinon.stub().resolves(expectedModel)
}
Profile.findOne.returns(findOneResult);
您还需要在响应对象上具有 status
函数 return 包含 send
函数的对象
//if we set up the stub to return the res object
//it returns the necessary func
res.status.returns(res);
我认为您不需要更改测试中的任何其他内容,它可能会像那样工作。请注意,您使用 sinon 2.0 或更新版本才能在存根上存在 resolves 函数(或者您可以将 sinon-as-promised 与 sinon 1.x)
一起使用这篇 post 更详细地介绍了如何处理这样的复杂对象: https://codeutopia.net/blog/2016/05/23/sinon-js-quick-tip-how-to-stubmock-complex-objects-such-as-dom-objects/