[英]Nodejs Expressjs Mongodb Javascript Unit Test Using Mocha Chai Sinon for random Nodejs Project
有人可以告诉我如何为函数 homeDog 的这个示例项目做“单元测试”吗? 我有以下来自随机项目的示例函数,我希望尝试为它添加单元测试,同时我学习如何使用 Mocha Chai Sinon 进行单元测试 引用来自https://github.com/seanaharrison/的示例随机 Nodejs 项目node-express-mongodb-example 。
我正在努力为 homeDog 功能进行单元测试,但后来我遇到了问题,有人可以向我展示一个关于如何为 homeDog 功能进行单元测试的工作单元测试,让我有一个起点吗?
这是我尝试过但失败的方法。
exports.homeDog = function(req, res) {
var db = req.db;
var collection = db.collection('dogs');
collection.find().toArray(function(err, dogsArray) {
if (dogsArray) {
res.render('index', {
title: 'Dogs',
path: req.path,
dogs: dogsArray
});
}
else {
res.render('index', {
title: 'No Dogs Found'
});
}
});
};
由于您需要一个“模拟数据库”,但您没有在代码中使用它(我认为),我将尝试解释如何使用mock database
测试 API 项目。
也就是说:您不需要真正的数据库来测试您的 API,您需要在每次执行测试时创建和关闭一个“内存数据库”。
首先是安装一个模拟依赖项,如mongo-mock 、 mongodb-memory-server或任何你想要的。
就个人而言,我使用mongodb-memory-server
。
所以按照文档你可以设置你的项目。 我有我的mockDB.js
在同一级别的文件test.js
。
mockDB.js
文件应该包含这样的内容(如果您使用另一个包,此代码可能会更改。):
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongod = new MongoMemoryServer();
module.exports.connect = async () => {
const uri = await mongod.getUri();
const mongooseOpts = {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true
};
await mongoose.connect(uri, mongooseOpts);
}
然后,您有一个文件,您的mock DB
将在其中初始化和连接。 此时,我的mongo DB
已初始化。 我正在使用mongoose
但允许使用另一种选择。
控制器(我认为在本例中为homeDog
)文件在这里无关紧要,因为您正在测试控制器,因此代码必须与生产中的代码相同。 控制器是要测试的代码,因此不应出于测试目的对其进行修改。
最后一个文件是test.js
。 在这个文件中,你必须导入你的mockDB.js
文件并启动数据库。
const mockDB = require('./mockDB');
...
before(async () => await mockDB.connect());
通过这种方式,您可以执行测试,控制器将执行对memory database
查询。 此外,您可以使用文件mockDB.js
来实现辅助查询。
例如,要从字段中获取特定值,您可以创建一个方法,如
module.exports.findValueById(id) => {
//return result
}
并在您的测试文件中调用此模块:
var idFound = mockDB.findValueById(id)
例如,您可以使用它在插入文档后查询数据库并检查集合是否正常。 或者检查更新是否正确或您想要的任何更新。
如果您的函数是GET
您只需将homeDog
返回的数据与现有的“模拟数据库”进行比较。
你提到了单元测试,这意味着它应该是一个孤立的测试(没有真正调用数据库)。 为此,您需要包含Sinon来模拟某些功能。
一些模拟功能:
db.collection
collection.find().toArray()
res.render
// include the sinon library
const sinon = require('sinon');
// include the source file that contain `homeDog` function
const src = require('./src');
describe('test', () => {
it('returns index with title, path and dogs if dogs array exist', () => {
const dogs = ['doggy', 'dogg2'];
// define mock `req` parameter
const mockReq = {
path: 'whatever',
db: {
collection: sinon.stub().returnsThis(), // `returnsThis` to mock chained function
find: sinon.stub().returnsThis(),
toArray: sinon.stub().callsFake(callback => {
callback(null, dogs) // specify dogs array here
})
}
};
// define mock `res` parameter
const mockRes = {
render: sinon.stub(),
}
src.homeDog(mockReq, mockRes); // pass the mock req and mock res to homeDog
// check whether the function is called correctly
sinon.assert.calledWith(mockReq.db.collection, 'dogs');
sinon.assert.calledWith(mockRes.render, 'index', { title: 'Dogs', path: 'whatever', dogs });
})
it('returns index with title', () => {
const mockReq = {
path: 'whatever',
db: {
collection: sinon.stub().returnsThis(),
find: sinon.stub().returnsThis(),
toArray: sinon.stub().callsFake(callback => {
callback(null, null) // give null value for dog array
})
}
};
const mockRes = {
render: sinon.stub(),
}
src.homeDog(mockReq, mockRes);
sinon.assert.calledWith(mockRes.render, 'index', { title: 'No Dogs Found' });
})
})
结果
test
✓ returns index with title, path and dogs if dogs array exist
✓ returns index with title
2 passing (12ms)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.