I have been working on a nodejs API that works with postgres and I'm having an issue testing with expect
. Sequelize is returning all fields as a string value no matter what the type is.
When using .toMatchObject
an error is thrown because in original object and in database id
is a numeric value, but is returned as a string. Same happens with decimal.
Is there a way to get data how it's stored, not as string?
Is there different way to check if objects match without having to parse each attribute to be same type as original ?
I tried using raw:true
as i read online, but it didnt work. Node version is 9.9, expect version is 22.4.3, sequelize version is 4.37
Testing code that fails is as follows:
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));
});
});
Error received is:
1) POST /zgrada should create new zgrada: Error: expect(received).toMatchObject(expected)
Object {
"dodatak_na_kucni_broj": "A",
"kucni_broj": "77",
- "sifra_zgrade": 1006,
+ "sifra_zgrade": "1006",
"ulica": "Derpa derpsona",
}
When I swap toMatchObject()
with .toBe()
then it works but I have to go through each attribute separately and cast the ones that are numeric to string first which is not practical for a bigger project with different models and many attributes.
edit: model definition (some attributes are left out but not relevant for error):
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 method:
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);
}
});
}
Thank you for help
Sequelize is returning all fields as a string value no matter what the type is.
Sequelize uses the pg
module as a bridge for postgres. In pg
, Decimal
(alias: Numeric
) type are returned as String
values by design for reasons concerned with the safety and precision of parseInt
in JS. For more information see this Issue on node-postgres Github .
Is there a way to get data how it's stored, not as string?
As of Sequelize version 4.32.5, an underlying dependency regarding type parsing was changed and there is an open issue with the same concern as this question linked here .
In short, there isn't much you can do with your current setup.
Other Solutions:
1) Use a different type such as DataTypes.UUID
or DataTypes.Integer
if possible. Especially given that sifra_zgrade
seems to be acting as an primary key/id column, it seems likely that the type could be changed.
2) Rollback to Sequelize version 4.23.3 and manually change how pg-types
parses decimals only if you're operating within a safe decimal precision range :
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 ?
As far as I understand, solutions would have to use underlying type-converting comparisons ( ==
) instead of strict equality comparisons.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.