测试mongoose pre-save hook

Mar*_*che 10 unit-testing mocha.js mongoose node.js 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);
Run Code Online (Sandbox Code Playgroud)

正如我所说的,我不想用我的测试命中数据库,所以我尝试使用Users 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();
        })
    })
});
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做,将不会调用预保存挂钩.我走错了路还是错过了什么?或者是否有其他方法可以触发预保存挂钩并测试其结果?首先十分感谢!

R. *_*sen 6

在开始之前:我正在寻找与您相同的东西,但是我还没有找到一种在没有数据库的情况下测试Mongoose中不同钩子的方法。我们必须区分测试代码和测试猫鼬,这一点很重要。

验证是中间件。猫鼬默认将验证注册为每个模式上的pre('save')钩子。http://mongoosejs.com/docs/validation.html

考虑到validate总是会添加到模型中,并且我希望测试模型中的自动字段,因此我从save切换到validate

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();
});
Run Code Online (Sandbox Code Playgroud)

现在,测试将如下所示:

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");
}
Run Code Online (Sandbox Code Playgroud)

那么预保存挂钩呢?

因为我已经将自动字段的业务逻辑从“保存”更改为“验证”,所以我将对数据库特定的操作使用“保存”。记录日志,将对象添加到其他文档,等等。测试只有与数据库集成才有意义。