You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:40:18