sequelize.js - 不应该存在的属性上的非空验证错误

标签 sequelize.js

我正在为使用 Sequelize 的节点服务器编写单元测试。插入一些假数据后,我收到错误

SequelizeValidationError: notNull Violation: QuestionId cannot be null

注意案例:QuestionId 上的大写 Q

单元测试:

describe('answerQuestion', () => {
    it('should insert an answer and get the next question', (done) => {
        Survey.DBModel.create({lookType: 0}, {logging: false}).then(() => {
            Question.DBModel.create({type: 0, text: 'Test question'}, {logging: false}).then(q1 => {
                Question.DBModel.create({type: 1, text: 'Next question'}, {logging: false}).then(q2 => {
                    console.log('before');
                    QuestionOption.DBModel.create({text: 'Test option', questionId: 1, nextQuestionId: 2}, {logging: false}).then(() => {
                        console.log('after');
                        Survey.answerQuestion(1, 1, 1).then(question => {
                            question.should.have.property('id');
                        }, done);
                    }, done);
                }, done);
            }, done);
        }, done);
    });
});

控制台输出 'before' 但在到达 'after' 之前出现错误

问题.js

'use strict';
module.exports = function(sequelize, DataTypes) {
  var Question = sequelize.define('Question', {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    type: {
      allowNull: false,
      type: DataTypes.INTEGER
    },
    text: {
      allowNull: false,
      type: DataTypes.STRING
    },
    nextQuestionId: {
      type: DataTypes.INTEGER
    }
  }, {
    classMethods: {
      associate: function(models) {
        models.Question.belongsTo(models.Question, {as: 'nextQuestion', foreignKey: {field: 'nextQuestionId', allowNull: true}});
        models.Question.hasMany(models.Answer, {as: 'answers', foreignKey: {field: 'questionId', allowNull: false}});
        models.Question.hasMany(models.QuestionOption, {as: 'options', foreignKey: {field: 'questionId', allowNull: false}});
        models.Question.hasMany(models.QuestionOption, {as: 'referrers', foreignKey: {field: 'nextQuestionId', allowNull: true}});
      }
    }
  });
  return Question;
};

问题选项.js

'use strict';
module.exports = function(sequelize, DataTypes) {
  var QuestionOption = sequelize.define('QuestionOption', {
    id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    questionId: {
      allowNull: false,
      type: DataTypes.INTEGER
    },
    text: {
      allowNull: false,
      type: DataTypes.STRING
    },
    nextQuestionId: {
      type: DataTypes.INTEGER
    }
  }, {
    classMethods: {
      associate: function(models) {
        models.QuestionOption.belongsTo(models.Question, {as: 'question', foreignKey: {field: 'questionId', allowNull: false}});
        models.QuestionOption.belongsTo(models.Question, {as: 'nextQuestion', foreignKey: {field: 'nextQuestionId', allowNull: true}});
      }
    }
  });
  return QuestionOption;
};

这些模型非常紧密地耦合在一起,并且具有自引用连接和各种其他困惑。我认为与此无关的所有其他模型,但可以在需要时提供。

直接在 SQLite 数据库上以与上述 create 语句相同的顺序和相同的属性执行 SQL 不会引发异常,并且通过大量测试很明显 Sequelize 不会尝试运行 QuestionOption 的 create 语句。它在生成要运行的 SQL 之前出错。

一些奇怪的行为是在模型中精心定义了关联,并且所有这些关联在它们的定义中都有一个小写的 q 用于 questionId。所有关联也定义了反向关联,因此 Sequelize 不应该尝试为属性创建名称。

在每次测试之前(成功)删除并重新创建所有表。

如果我从 QuestionOption 的 create 语句中删除 questionId: 1,那么错误就变成了正在发生的奇怪事情的证据
SequelizeValidationError: notNull Violation: questionId cannot be null, 
notNull Violation: QuestionId cannot be null

注意两者的 shell ,一个在下方(我拆下的那个),一个在上方。

下一个怀疑是 nextQuestionId 关联,但它已在模型中定义,关联的每一侧都为 allowNull: true,我在 create 语句中提供了它。

我完全对这种行为感到困惑,并质疑这是否可能是 Sequelize 中的错误,尽管我需要在错误报告之前确认这一点。

其他可能有用的信息是:
  • 使用命令 NODE_ENV=test mocha
  • 运行测试
  • 使用 sync(下面的代码)为测试创建数据库是自动的
  • 所有其他测试都通过,但这是测试中唯一使用 QuestionOption 的测试。
  • 我试图测试的方法“在生产中”有效(在开发中本地运行并连接客户端)
  • 数据库架构已使用 SQLite GUI 进行验证,所有列都适用(任何带有大写 Q 的表中都没有 QuestionId 字段)

  • 为测试创建数据库

    beforeEach((done) => {
        Survey.DBModel.sync({force: true, logging: false}).then(() => {
            Question.DBModel.sync({force: true, logging: false}).then(() => {
                Answer.DBModel.sync({force: true, logging: false}).then(() => {
                    QuestionOption.DBModel.sync({force: true, logging: false}).then(() => {
                        done();
                    }, done);
                }, done);
            }, done);
        }, done);
    });
    

    最佳答案

    因此,在寻找答案并创建测试副本之后。事实证明,这是 Sequelize 的一个已知问题。解决方案,或者说是一种肮脏的解决方法,是添加明显的“缺失”属性,然后查询将起作用,并且会抛出分配给 ghost 属性的值。

    describe('answerQuestion', () => {
        it('should insert an answer and get the next question', (done) => {
            Survey.DBModel.create({lookType: 0}, {logging: false}).then(() => {
                Question.DBModel.create({type: 0, text: 'Test question'}, {logging: false}).then(q1 => {
                    Question.DBModel.create({type: 1, text: 'Next question'}, {logging: false}).then(q2 => {
                        QuestionOption.DBModel.create({
                            text: 'Test option', 
                            questionId: 1,
                            QuestionId: 1, <------ Workaround
                            nextQuestionId: 2}, {logging: false}).then(() => {
                            Survey.answerQuestion(1, 1, 1).then(question => {
                                question.should.have.property('id');
                            }, done);
                        }, done);
                    }, done);
                }, done);
            }, done);
        });
    });
    

    可以找到已知问题 here

    使用此问题 here 测试重现(如果更改,将删除链接)

    希望这可以帮助其他人解决这个问题。我确实希望这至少在他们的文档中被记录为一个已知问题......

    关于sequelize.js - 不应该存在的属性上的非空验证错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33981007/

    相关文章:

    sequelize.js - Sequelize : How to make relationship between 3 tables

    mysql - Sequelize - 表多元化错误,表中没有实例

    node.js - Openshift Node 应用程序无法启动

    sql - 带有许多 :many join is very slow 的 PostgreSQL 查询

    javascript - Nodejs 在 sequelize 上对两个表使用 JOIN

    node.js - 试图将 sequelize 查询的结果传递给 pug

    javascript - 跨 Sequelize 关联播种数据

    node.js - "ER_BAD_FIELD_ERROR: Unknown column ' id ' in ' 字段列表 '"sequelize with nodejs

    javascript - 如何在nodejs中使用sequelize设置模型验证?

    node.js - 如何在 Node.JS 中向 sequelize.js 添加自定义函数?