对于不应存在的属性,不为null验证错误

时间:2015-11-29 08:53:09

标签: 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);
    });
});

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

之前的错误

question.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;
};

questionoption.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数据库上执行SQL,与上面的create语句具有相同的顺序和相同的属性不会引发异常,并且通过大量测试很明显Sequelize不会尝试为{运行create语句{1}}。在生成要运行的SQL之前,它会出错。

一些奇怪的行为是模型中的关联被精心定义,并且所有关联在其定义中都有{em>小写 QuestionOption q。所有关联也定义了反向关联,因此Sequelize不应该尝试为属性创建名称。

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

如果我从QuestionOption的create语句中删除了questionId,那么添加一些奇怪的证据是错误的,那么错误就会变成

questionId: 1

注意两者的外壳,一个是较低的(我移除了一个),一个是上部。

下一个嫌疑人是SequelizeValidationError: notNull Violation: questionId cannot be null, notNull Violation: QuestionId cannot be null 关联,但它已在模型中定义,关联的每一方都为nextQuestionId 我已在创建中提供言。

我对此行为感到困惑,并质疑这可能是续集中的错误,但我需要在错误地报告之前确认这一点。

其他可能有用的信息是:

  • 使用命令allowNull: true
  • 运行测试
  • 使用NODE_ENV=test mocha(下面的代码)
  • 自动创建测试数据库
  • 所有其他测试都通过,但这是唯一一个在测试中使用QuestionOption的测试。
  • 我试图测试的方法"在生产中#34; (在连接客户端的dev中本地运行)
  • 已使用SQLite GUI验证数据库架构,并且所有列都适当(任何具有大写Q的表中的{sync字段)

为测试创建数据库

QuestionId

1 个答案:

答案 0 :(得分:0)

所以在挖掘答案并创建测试repro之后。事实证明,这是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

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

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