Javascript 路由内模拟mongoose save()错误

Javascript 路由内模拟mongoose save()错误,javascript,mongoose,sinon,Javascript,Mongoose,Sinon,在尝试了各种方法来测试路由的mongoosesave()抛出之后,我真的不确定该如何做。我的目标是在伊斯坦布尔实现100%的覆盖率。以下是核心设置: model.js let mongoose = require('mongoose'); let Schema = mongoose.Schema; let PasteSchema = new Schema( { message: { type: String, required: true }, tags: [String]

在尝试了各种方法来测试路由的mongoose
save()
抛出之后,我真的不确定该如何做。我的目标是在伊斯坦布尔实现100%的覆盖率。以下是核心设置:

model.js

let mongoose = require('mongoose');
let Schema = mongoose.Schema;

let PasteSchema = new Schema(
  {
    message: { type: String, required: true },
    tags: [String],
    marked: { type: Boolean, default: false },
    createdAt: { type: Date, default: Date.now },
    updatedAt: Date
  }
);

module.exports = mongoose.model('paste', PasteSchema);
controller.js

let Paste = require('./model');

// Other stuff

// I use a bit non-standard DELETE /pastes/:id for this
const markPaste = (req, res) => {
  Paste.findById({ _id: req.params.id }, (err, paste) => {
    if (!paste) {
      res.status(404).json({ result: 'Paste not found' });
      return;
    }
    paste.marked = true;
    paste.updatedAt = new Date();
    paste.save((err) => {
      err
        ? res.status(400).json({ result: err })
        : res.json({ result: 'Paste marked' });
    });
  });
}

module.exports = {
  markPaste,
  // Other stuff
}
routes.js

const express = require('express');
const app = express();
const pastes = require('./apps/pastes/controller'); // The file above

app.route('/pastes/:id')
  .delete(pastes.markPaste);

module.exports = app;
在下面的测试中,我想模拟在上面的
paste.save((err)=>{
中抛出的错误

process.env.NODE_ENV = 'test';

let mongoose = require('mongoose');
let Paste = require('../apps/pastes/model');
let server = require('../index');

let chai = require('chai');
chai.use(require('chai-http'));
chai.use(require('chai-date-string'));
let expect = chai.expect;
let sinon = require('sinon');
let sandbox = sinon.createSandbox();
let pastes = require('../apps/pastes/controller');
let httpMocks = require('node-mocks-http');

// Other tests
然后,我要测试的测试路径中的
save()
错误:

it('should handle an error during the save in the endpoint', (done) => {
  // Create a paste to be deleted
  const pasteItem = new Paste({ message: 'Test 1', tags: ['integration', 'test'] });
  pasteItem.save()
    .then((paste) => {
      // Attempt code from below goes here
    })
    .catch((err) => {
      console.log('Should not go here');
    });
  done();
});

我在各种堆栈问题或在线问题中都没有找到任何明确的参考,所以我是这样做的:

秘密在于使用
sinon
沙箱,它甚至在测试期间应用于路由上下文中。以下是工作测试:

it('should handle an error during the save in the endpoint', (done) => {
  const pasteItem = new Paste({ message: 'Test 1', tags: ['integration', 'test'] });
  pasteItem.save()
    .then((paste) => {
      // the sandbox is defined in the imports
      // This forces calling save() to raise an error
      sandbox.stub(mongoose.Model.prototype, 'save').yields({ error: 'MongoError' });
      chai.request(server)
        .delete('/pastes/' + paste._id)
        .end((err, res) => {
          // It applies within the route handling, so we get the expected 400
          expect(res).to.have.status(400);
          done();
        });
    })
    .catch((err) => {
      console.log('Should not go here');
    });
});
如果您在沙箱之外调用它,您将破坏所有使用
sinon
的后续测试

// This would break things unintendedly
sinon.stub(mongoose.Model.prototype, 'save').yields({ error: 'MongoError' });

// This only breaks things (on purpose) in the test we want it to break in:
sandbox.stub(mongoose.Model.prototype, 'save').yields({ error: 'MongoError' });
如果在特定的
sandbox
实例中有多个对象,当然可以在测试用例之后使用
sandbox.restore();
恢复测试中的“未中断”状态

->

=============================== Coverage summary ===============================
Statements   : 100% ( 60/60 )
Branches     : 100% ( 14/14 )
Functions    : 100% ( 0/0 )
Lines        : 100% ( 57/57 )
================================================================================