Mongoose虚拟字段set方法未正确赋值passwordHash问题求助
解决Mongoose虚拟字段setter无法赋值passwordHash的问题
嘿,我一眼就看到问题所在了——你在虚拟字段的getter和setter里用了箭头函数,这直接导致this的指向完全不对,没法正确操作Mongoose的文档实例!
问题根源
箭头函数不会绑定自己的this,它会捕获定义时所在上下文的this(这里大概率是全局对象或者模块上下文),而不是当前的Mongoose用户文档对象。所以你在setter里给this._password和this.passwordHash赋值时,根本没修改到新建的user实例,passwordHash自然还是空的,触发了必填字段的验证错误。
修复方案
把虚拟字段的箭头函数换成普通函数,这样this就会指向当前的文档实例了:
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const userSchema = new Schema({ name: {type: String, required: true}, email: {type: String, required: true}, passwordHash: {type: String, required: true} }); // 换成普通函数,确保this指向文档实例 userSchema.virtual("password") .get(function() { return this._password; }) .set(function(val) { this._password = val; console.log("setting: ", val); this.passwordHash = "test"; // 现在能正确赋值到文档的passwordHash字段了 }) module.exports = mongoose.model("Users", userSchema);
额外的测试用例优化
你的测试用例还有个小问题:user.validate是异步方法,你现在的写法会让done()在验证完成前就执行,可能导致测试结果不准确。应该把done放到验证的回调里,同时注意validate的回调参数是错误对象本身,不是解构出来的errors:
it("should not save passwords as plain test", done => { const user = new User({name: "john", email: "john@example.com", password: "password1234"}); console.log(user); user.validate(err => { expect(err).to.not.exist; done(); // 验证完成后再调用done,确保异步流程正确 }); });
这样修改后,虚拟字段的setter就能正确给passwordHash赋值,测试应该就能通过了。另外,实际项目中记得把"test"换成真正的密码哈希逻辑(比如用bcrypt)哦!
内容的提问来源于stack exchange,提问作者EuklidianSpace
相关产品推荐
相关产品推荐

