测试mongoose pre-save hook

时间:2017-09-22 17:40:42

标签: node.js unit-testing mongoose mocha sinon

我对测试nodejs很陌生。所以我的方法可能完全错误。我尝试在没有命中数据库的情况下测试mongoose模型pre-save-hook。这是我的模特:

// models/user.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;

UserSchema = new Schema({
    email: {type: String, required: true},
    password: {type: String, required: true}    
});

UserSchema.pre('save', function (next) {
    const user = this;
    user.email = user.email.toLowerCase();
    // for testing purposes
    console.log("Pre save hook called");
    next();
});

module.exports = mongoose.model("User", UserSchema);

正如我所说,我不想用我的测试点击数据库,所以我尝试使用了用户save()方法的sinon存根:

// test/models/user.js
const sinon = require("sinon");
const chai = require("chai");
const assert = chai.assert;

const User = require("../../models/user");

describe("User", function(){
    it("should convert email to lower case before saving", (done) => {
        const user = new User({email: "Valid@Email.com", password: "password123"});
        const saveStub = sinon.stub(user, 'save').callsFake(function(cb){ cb(null,this) })

        user.save((err,res) => {
            if (err) return done(err);
            assert.equal(res.email,"valid@email.com");
            done();
        })
    })
});

但是,如果我这样做,则不会调用预保存挂钩。我走错了路还是错过了什么?或者是否有其他方法可以触发预保存挂钩并测试其结果?非常感谢提前!

2 个答案:

答案 0 :(得分:6)

在我们开始之前:我正在寻找与您相同的事情,而且我还没有找到一种方法来测试没有数据库的Mongoose中的不同挂钩。我们区分测试代码和测试猫鼬是非常重要的。

  

验证是中间件。默认情况下,Mongoose将验证注册为每个模式的前(' save')挂钩。 http://mongoosejs.com/docs/validation.html

考虑到将始终将验证添加到模型中,并且我希望测试模型中的自动字段,我已从保存切换到验证

UserSchema = new Schema({
  email: {type: String, required: true},
  password: {type: String, required: true}    
});

UserSchema.pre('validate', function(next) {
  const user = this;
  user.email = user.email.toLowerCase();
  // for testing purposes
  console.log("Pre validate hook called");
  next();
});

测试现在看起来像:

it("should convert email to lower case before saving", (done) => {
    const user = new User({email: "VALID@EMAIL.COM", password: "password123"});
    assert.equal(res.email,"valid@email.com");
}

那么Pre Save Hook呢?

因为我已经移动了自动字段的业务逻辑来保存'为了验证',我将使用' save'用于数据库特定操作。记录,将对象添加到其他文档等。只有与数据库集成才能测试这一点。

答案 1 :(得分:0)

我只是面临着同样的问题,并设法通过从逻辑中提取逻辑来解决它,从而有可能进行独立测试。隔离是指不测试任何猫鼬相关的东西。

您可以通过创建具有以下结构的函数来执行逻辑来实现此目的:

function preSaveFunc(next, obj) {
  // your logic
  next();
}

然后您可以在钩子中调用它:

mySchema.pre('save', function (next) { preSaveFunc(next, this); });

这将在函数内部提供对此的引用,因此您可以使用它。

然后可以通过将下一个功能重写为没有主体的功能来对提取的部分进行单元测试。

希望这将对任何人都有帮助,因为我对猫鼬的了解有限,这实际上是一个痛苦的解决。