测试将 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 的桥梁。在 pg
、Decimal
(别名: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.UUID
或 DataTypes.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 比较 (==
) 而不是严格的相等比较。
我一直在开发一个与 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 的桥梁。在 pg
、Decimal
(别名: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.UUID
或 DataTypes.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 比较 (==
) 而不是严格的相等比较。