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

使用Jest测试Node.js Sequelize模型时spyOn save方法报非函数错误

问题根因

你遇到的两个报错本质是同一个问题触发的:Sequelize的save是模型实例方法,不属于模型类的静态方法,你直接对模型类执行spy、直接调用模型类的自定义方法都会找不到对应函数。

Cannot spy the save property because it is not a function; undefined given instead是因为你spy的对象是模型类,类上没有save静态方法。
删除spy后报TypeError: this.save is not a function是因为你调用generateToken时用了模型类直接调用,方法内部的this指向模型类而非实例,自然找不到实例方法save。

修复步骤
  1. 修正自定义方法的定义,确保是实例方法
    如果用class继承的方式定义模型,不要给generateToken加static修饰符:
const { Model } = require('sequelize')
class 你的模型类名 extends Model {
  // 不加static就是实例方法,this指向当前模型实例
  generateToken() {
    return generateTokenHash(20)
      .then((token) => {
        this.token = token;
        return this.save();
      });
  }
}
// 后续初始化模型代码省略

如果用旧版sequelize.define的方式定义模型,要把方法挂到模型原型上:

const 你的模型 = sequelize.define('模型名', {
  // 字段定义省略
})
// 挂载实例方法
你的模型.prototype.generateToken = function() {
  return generateTokenHash(20)
    .then((token) => {
      this.token = token;
      return this.save();
    });
}
  1. 修正测试代码,操作模型实例而非模型类
    测试时先创建模型实例,对实例的save方法进行spy:
const 你的模型 = require('/path/to/your/model')

describe('你的测试分组名', () => {
  it('你的测试用例名', async () => {
    // 创建模型实例,build方法不会真实写入数据库,适合单元测试
    const modelInstance = 你的模型.build({
      // 补充模型必填字段的默认值即可
    })
    // 对实例的save方法做spy,根据需要可以mock返回值避免真实操作数据库
    const saveSpy = jest.spyOn(modelInstance, 'save').mockResolvedValue(modelInstance)

    // 调用实例的generateToken方法
    await modelInstance.generateToken()

    // 这里补充你自己的断言逻辑,比如:
    expect(saveSpy).toHaveBeenCalledTimes(1)
    expect(modelInstance.token).not.toBeUndefined()
  })
})
可选优化

如果不需要测试数据库写入逻辑,可以在spy时直接mocksave的返回,避免测试依赖数据库环境,提升测试运行速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 06:24:02