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

类型声明正常,CI环境运行Mongoose测试却报ValidationError?

Mongoose在GitHub Actions测试中出现字符串转换验证错误的问题

在GitHub Actions运行单元测试插入新的MySchema文档时,遇到如下错误:

ValidationError: MySchema validation failed: name: Cast to String failed for value "some-string" (type string) at path "name" because of "TypeError"

明明传入的是字符串,却触发类型转换失败的验证错误,且该问题仅在GitHub Actions环境出现,本地、测试及生产环境均未复现。

相关代码

Schema定义:

var MySchema = {
  ...
  name: { type: String, get: encryption.decrypt, set: encryption.encrypt },
  ...
}

测试工具代码:

const generateMySchema = ({ name, ...rest }) => {
  const name = `test_myschema_${Date.now()}`;
  let myTestSchema = new MySchema({
    name,
    ...rest
  });
  return myTestSchema;
};

目前临时通过关闭CI环境的前置验证解决,但会丢失测试验证能力:

var validateBeforeSave = process.env.NODEJS_ENV !== "test-ci";
MySchema.set("validateBeforeSave", validateBeforeSave);

使用版本:Mongoose 6.10.1,MongoDB 5.0.6


问题分析与解决方法

1. 排查加密解密函数的CI环境兼容性

错误的核心是Mongoose将encryption.encrypt或encryption.decrypt执行时抛出的TypeError包装成了类型转换失败的验证错误。需要确认:

  • 加密解密依赖的密钥、环境变量是否在GitHub Actions中正确注入
  • 加密库在CI环境中的版本是否与本地一致(可通过锁定package-lock.json确保依赖版本统一)

2. 给加密函数添加错误日志与捕获

在CI环境中添加日志定位问题,修改加密函数:

const encryption = {
  encrypt: (val) => {
    console.log('[CI Debug] Encrypting name:', val);
    try {
      // 原加密逻辑
      const encryptedVal = /* 你的加密代码 */;
      console.log('[CI Debug] Encrypted result:', encryptedVal);
      return encryptedVal;
    } catch (err) {
      console.error('[CI Debug] Encryption failed:', err.stack);
      throw err; // 保留错误让Mongoose捕获,或抛出明确的验证错误
    }
  },
  decrypt: (val) => {
    console.log('[CI Debug] Decrypting name:', val);
    try {
      const decryptedVal = /* 你的解密代码 */;
      console.log('[CI Debug] Decrypted result:', decryptedVal);
      return decryptedVal;
    } catch (err) {
      console.error('[CI Debug] Decryption failed:', err.stack);
      throw err;
    }
  }
};

查看GitHub Actions的日志输出,就能直接找到触发TypeError的原因。

3. 修复钩子的错误处理逻辑

避免Mongoose误判错误类型,在钩子中明确处理异常:

name: { 
  type: String, 
  get: (val) => {
    try {
      return encryption.decrypt(val);
    } catch (err) {
      console.error('Decryption error for name:', err);
      // 可选择返回默认值或抛出明确的ValidationError
      throw new mongoose.Error.ValidationError(null, {
        name: new mongoose.Error.ValidatorError({
          message: `Failed to decrypt name: ${err.message}`,
          path: 'name',
          type: 'decryption_failed'
        })
      });
    }
  },
  set: (val) => {
    try {
      return encryption.encrypt(val);
    } catch (err) {
      console.error('Encryption error for name:', err);
      throw new mongoose.Error.ValidationError(null, {
        name: new mongoose.Error.ValidatorError({
          message: `Failed to encrypt name: ${err.message}`,
          path: 'name',
          type: 'encryption_failed'
        })
      });
    }
  }
},

4. 测试环境临时替换加密逻辑(保留验证能力)

如果CI环境的加密问题暂时无法解决,可在测试中临时替换加密解密函数为原函数,既保留Mongoose的验证,又避免CI环境的加密异常:

// 在测试文件的全局前置钩子中
beforeAll(() => {
  // 保存原函数
  global.__originalEncrypt = encryption.encrypt;
  global.__originalDecrypt = encryption.decrypt;
  // 替换为原数据返回
  encryption.encrypt = (val) => val;
  encryption.decrypt = (val) => val;
});

afterAll(() => {
  // 测试结束后恢复原函数
  encryption.encrypt = global.__originalEncrypt;
  encryption.decrypt = global.__originalDecrypt;
});

内容的提问来源于stack exchange,提问作者Moshisho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:33:24