测试将 Sequelize 与 Mocha/Expect/Supertest 结合使用的 Node.js API

Testing Node.js API that uses Sequelize with Mocha/Expect/Supertest

我一直在开发一个与 postgres 一起工作的 nodejs API,但我在使用 expect 进行测试时遇到了问题。 Sequelize 将所有字段作为字符串值返回,无论类型是什么。

当使用 .toMatchObject 时会抛出错误,因为在原始对象和数据库中 id 是一个数值,但作为字符串返回。十进制也是如此。

有没有办法获取数据的存储方式,而不是字符串?

是否有不同的方法来检查对象是否匹配,而不必将每个属性解析为与原始属性相同的类型?

我在网上阅读时尝试使用 raw:true,但没有用。 Node版本是9.9,expect版本是22.4.3,sequelize版本是4.37

测试失败代码如下:

it('should create new zgrada', (done) => {
    var newZgrada = {
        sifra_zgrade: 1006,
        ulica: "Derpa derpsona",
        kucni_broj: "77",
        dodatak_na_kucni_broj: "A"
    };
    request(app)
        .post('/zgrade')
        .send(newZgrada)
        .expect(200)
        .expect((res) => {
            expect(res.body.zgrada).toMatchObject(newZgrada);
        })
        .end((err, res) => {
            if (err) {
                return done(err);
            }

            db.zgrada.findAll({
                where: {
                    sifra_zgrade: newZgrada.sifra_zgrade
                }
            }).then((zgrada) => {
                expect(zgrada.length).toBe(1);
                expect(zgrada).toMatchObject(newZgrada);
                done();
            }).catch((e) => done(e));
        });
});

收到的错误是:

1) POST /zgrada 应该创建新的 zgrada: 错误:expect(received).toMatchObject(expected)

  Object {
    "dodatak_na_kucni_broj": "A",
    "kucni_broj": "77",
-   "sifra_zgrade": 1006,
+   "sifra_zgrade": "1006",
    "ulica": "Derpa derpsona",
  }

当我将 toMatchObject().toBe() 交换时它可以工作,但我必须分别检查每个属性并将数字属性首先转换为字符串,这对于更大的项目来说是不实用的不同的模型和许多属性。

编辑:模型定义(一些属性被遗漏但与错误无关):

module.exports = (sequelize, DataTypes) => {
var Zgrada = sequelize.define('zgrada', {
    sifra_zgrade: {
        type: DataTypes.NUMERIC(0, 4),
        unique: true,
        primaryKey: true,
        allowNull: false
    },
    ulica: {
        type: DataTypes.STRING,
        allowNull: false
    },
    postanski_broj: {
        type: DataTypes.STRING
    },
    kucni_broj: {
        type: DataTypes.STRING
    },
    dodatak_na_kucni_broj: {
        type: DataTypes.STRING
    }
}

Post方法:

router
    .post("/", async (req, res) => {
        try {
            var body = req.body;
            var zgrada = await db.zgrada.create({
                sifra_zgrade: body.sifra_zgrade,
                ulica: body.ulica,
                kucni_broj: body.kucni_broj,
                dodatak_na_kucni_broj: body.dodatak_na_kucni_broj,
            });
            res.send({
                zgrada
            });
        } catch (e) {
            res.status(400).send(e);
        }
    });
}

感谢您的帮助

Sequelize is returning all fields as a string value no matter what the type is.

Sequelize 使用 pg 模块作为 postgres 的桥梁。在 pgDecimal(别名:Numeric)中,出于与 JS 中 parseInt 的安全性和精度有关的原因,类型按设计返回为 String 值。 For more information see this Issue on node-postgres Github

Is there a way to get data how it's stored, not as string?

从 Sequelize 版本 4.32.5 开始,关于类型解析的底层依赖关系发生了变化,并且有一个 open issue with the same concern as this question linked here.

简而言之,您当前的设置无能为力。

其他解决方案:

1) 如果可能,请使用不同的类型,例如 DataTypes.UUIDDataTypes.Integer。特别是考虑到 sifra_zgrade 似乎充当主要 key/id 列,似乎可以更改类型。

2) 回滚到 Sequelize 版本 4.23.3 并手动更改 pg-types 解析小数的方式 仅当您在安全的小数精度范围内操作时:

var pg = require('pg');
pg.types.setTypeParser(1700, 'text', parseFloat);

Is there different way to check if objects match without having to parse each attribute to be same type as original ?

据我了解,解决方案必须使用基础 type-converting 比较 (==) 而不是严格的相等比较。