2015-11-29 27 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

測試瑞普(如果更改將刪除鏈接)

希望這有助於任何人有這個問題。我希望這至少在其文檔中記錄爲已知問題...

相關問題