繁体   English   中英

Nodejs Expressjs Mongodb Javascript 单元测试使用 Mocha Chai Sinon 进行随机 Nodejs 项目

[英]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 功能进行单元测试的工作单元测试,让我有一个起点吗?

这是我尝试过但失败的方法。

what_i_had_done_but_failed

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-mockmongodb-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来模拟某些功能。

一些模拟功能:

  1. db.collection
  2. collection.find().toArray()
  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM