如何覆盖sequelize defaultValue函数以进行测试?

时间:2016-06-14 00:43:01

标签: javascript postgresql sqlite sequelize.js

我正在尝试将单元/集成测试添加到我的续集项目中,当从postgres方言转换为sqlite时,我遇到了一个问题。我试图覆盖'id'上的'defaultValue'函数。这导致CREATE TABLE的语法正确,但原始的defaultValue在.create()生成的INSERT语句中使用。

我创建了一个minimal sample project来说明我在测试失败时所描述的问题。

以下是相关的代码段:

    User = sequelize.define('User', {
    id: {
      type: Sequelize.UUID,
      field: 'id',
      defaultValue: sequelize.literal("uuid_generate_v1mc()"),
      primaryKey: true
    },
    name: {
      type: Sequelize.STRING,
      field: "first_name"
    },
});

// why doesn't setting these attributes override the default value
// provided by User.create?
User.attributes.id.defaultValue='b9c96442-2c0d-11e6-b67b-9e71128cae77';
User.tableAttributes.id.defaultValue='b9c96442-2c0d-11e6-b67b-9e71128cae77';

注入或模拟defaultValue函数的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

答案会错过“为什么”部分,但这就是我如何运作:

before(function() {
    // Define a table that uses a custom default value
    User = sequelize.define('User', {
        id: {
          type: Sequelize.UUID,
          field: 'id',
          defaultValue: sequelize.literal("uuid_generate_v1mc()"),
          primaryKey: true
        },
        name: {
          type: Sequelize.STRING,
          field: "first_name"
        },
    });

    User.attributes.id.defaultValue.val = '"b9c96442-2c0d-11e6-b67b-9e71128cae77"';

    return sequelize.sync();
});

尽管如此,我怀疑应该有一种更简单的方法来实现相同的结果。

有趣的是,如果defaultValue不是literalfn而是一个字符串值,事情会更容易 - 我们可以只是添加了一个钩子:

User.beforeCreate(function (user) {
  user.dataValues.id = 'b9c96442-2c0d-11e6-b67b-9e71128cae77';
});

我建议你在sequelize issue tracker找到“为什么”问题的答案。