2015-11-29 28 views
1

我正在为使用Sequelize的节点服务器编写单元测试。在一些假的数据插入我收到错误不应该存在的验证错误应该不存在的属性

SequelizeValidationError: notNull Violation: QuestionId cannot be null 

注意的情况:资本Q上QuestionId

单元测试:

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语句QuestionOption。它在生成要运行的SQL之前发生错误。

一些奇怪的行为是有关联模型中定义的精心和他们都有一个小写q对它们的定义questionId。所有关联都有一个反向关联定义,所以Sequelize不应该试图为属性创建名称。

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

添加到的证据表明,一些奇怪的事情是,如果我从QuestionOption创建语句删除questionId: 1,那么误差变得

SequelizeValidationError: notNull Violation: questionId cannot be null, 
notNull Violation: QuestionId cannot be null 

注意两者的外壳,一个较低(在一个我删除),一个是上层。

下一页疑是nextQuestionId关联,但它已经在模型中定义,每个关联方为allowNull: true和我在创建语句,只要它

我完全对这种行为感到困惑,并质疑这是否是一个后续错误,尽管我需要在错误地报告之前确认这一点。

其他信息,也许可能是有用的是:

  • 测试使用的是命令NODE_ENV=test mocha
  • 数据库创建用于测试的自动使用sync(下面的代码)
  • 其他所有测试都通过了运行,但这是测试中唯一使用QuestionOption的人。
  • 我试图测试“生产”的作品
  • 数据库模式已经证实了SQLite的GUI和所有列是适当的(没有QuestionId领域中的任何表(在开发中与所连接的客户端在本地运行)的方法资本Q)

数据库创建用于测试

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); 
}); 

回答

0

于是四处寻找答案,并创建一个测试摄制后。事实证明,这是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); 
    }); 
}); 

已知的问题,可以发现这个问题herehere

测试瑞普(如果更改将删除链接)

希望这有助于任何人有这个问题。我希望这至少在其文档中记录为已知问题...

相关问题