簡體   English   中英

單元測試 node.js mongoose mocha chai sinon

[英]unit test node.js mongoose mocha chai sinon

我是單元測試的新手。 我的 Web API 項目是基於 node-express-mongoose 的 MVC。

我有一個conroller.js如下:

const getComments = async (req, res) => {
  let query = {};

  try {
    query = req.query.filter ? { email: new RegExp(`.*${req.query.filter}.*`, 'i') } : query;
    const comments = await util.getComments(query);
    return res.json(comments);
  } catch (err) {
    return res.status(500).send(`Internal server error: ${err}`);
  }
};

控制器使用util.js函數來實現所有數據庫操作:

const comments = require('../models/comments');

exports.getComments = (query) => {
      try {
        return comments.find(query).sort({ createdAt: -1 });
      } catch (err) {
        throw err;
      }
};

如何使用 mocha & chai 創建單元測試? 我是否必須使用 sinon 等創建假模擬?

如果我想對不模擬 db 就無法避免的方法編寫測試,我使用mongodb-memory-server作為數據庫並模擬 mongodb 行為。

const Comment = require('../models/comments');

const mockedComments = [ // modify example data depending on Your model
  {userId: "1", body: "Mocked comment of user 1", createdAt: Date.now() },
  {userId: "2", body: "Mocked comment of user 2", createdAt: Date.now() },
];

const getComments = require('../path/to/getComments');


const mongoose = require('mongoose');
const MongodbMemoryServer = require('mongodb-memory-server');

let mongoServer;
const opts = { useMongoClient: true }; 

before((done) => {
  mongoServer = new MongodbMemoryServer();

  mongoServer.getConnectionString()
    .then((mongoUri) => {
      return mongoose.connect(mongoUri, opts, (err) => {
        if (err) done(err);
      });
    })
    .then(() => {
     // preparing in memory database contents 
     Promise.all([
       Comment.create(mockedComments[0]),
       Comment.create(mockedComments[1])
     ]).then(() => done());
    });
});

after(() => {
  mongoose.disconnect();
  mongoServer.stop();
});

describe('getComments', () => {

  it('successfully returns comments', async () => {
    const result = await getComments({});
    expect(result.length).to.equal(mockedComments.length);
  });

  it('successfully returns comments of user', async () => {
    const result = await getComments({userId: 1});
    expect(result[0].userId).to.equal(1);
  });
});

等等....

問題說明我們在談論“單元測試”,因此單元測試是我們評估函數/類/我們開發的任何內容的正確行為的那些測試。 只是這個和其他任何東西。 現在,太糟糕了,我不是 mongoDB 開發人員,也不是 mongo-memory-server 貢獻者,所以我真的不需要在我的測試中考慮這些軟件。 這就是測試替身(存根/模擬/間諜)誕生的原因,作為優秀的軟件工程師,我們應該明智地使用它們

所以,這是我的單元測試:

 const {expect} = require("chai") const sinon = require("sinon") const uut = require("./users.service") const UserModel = require("./user.model") it("given correct userId should retrieve users full name" , async () => { //given const fixture = { _id : "fakeuser", name: "Fake", surname: "User" } let stub = sinon.stub(UserModel , "findById").returns(fixture) //when let result = await uut.getUserFullnameById(fixture._id) //then expect(result).to.eq("Fake User") stub.restore() })

這個測試告訴我 getUserFullnameById 函數行為正確,

 const User = require("./user.model") module.exports.getUserFullnameById = async function (userId) { let user = await User.findById(userId) return `${user.name} ${user.surname}` }

我將我的邏輯與 mongoose 隔離,因為我不需要知道 mongoose 是否有效並且我能夠連接到底層 mongodb 實例。 所以有人可能會指出,即使 mongoose 庫中沒有“findById”API,我的測試也通過了,這就是我依賴集成測試的原因

 describe("integration test" , () => { const mongoose = require("mongoose") before(()=> { mongoose.connect("mongodb://localhost:27017/db" , { useNewUrlParser: true , useUnifiedTopology: true}) mongoose.Promise = global.Promise }) beforeEach(async ()=> { await mongoose.connection.dropDatabase() }) it("given correct userId should retrieve users full name" , async () => { let fixture = new UserModel({name : "Fake" , surname : "User"}) await fixture.save() let result = await uut.getUserFullnameById(fixture._id) expect(result).to.eq("Fake User") }) })

集成測試和以前做同樣的事情,但它是在上下文中進行的。 如果我弄亂了我的測試方法,我可能會破壞集成測試,我會知道我在濫用 mongoose 或 mongodb 連接,或者我可以破壞兩者,所以我知道我可能只是不尊重我的業務規則。 另一個優點:集成測試緩慢且脆弱,但我可以提供高質量的代碼,即使提供更少的代碼並添加更多的隔離單元測試

現在您還有兩種情況:名字不存在和姓氏不存在:您如何測試和擴展您的代碼?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM