使用Mocha/Expect/Supertest测试Sequelize Node.js API遇类型匹配问题
解决Sequelize返回PostgreSQL字段类型为字符串的问题
这事儿我之前在项目里也碰到过——Sequelize默认配置下,PostgreSQL的数值类型(比如INT、DECIMAL)会被转成字符串返回,确实会搞砸Expect的toMatchObject校验。下面给你几个实用的解决思路,从根源修复到临时测试兼容都有:
一、从根源修复:让Sequelize正确映射PostgreSQL类型
这是最优解,一劳永逸解决所有查询的类型问题:
1. 启用原生PostgreSQL驱动
如果你用的是Sequelize v5及以上版本,可以开启native选项,让Sequelize使用pg-native驱动(需要先安装依赖:npm install pg-native)。原生驱动会直接映射PostgreSQL的类型到JavaScript对应类型,不用手动配置:
const Sequelize = require('sequelize'); const sequelize = new Sequelize('your_db', 'user', 'password', { host: 'localhost', dialect: 'postgres', native: true, // 关键配置:启用原生驱动 });
2. 手动配置类型解析(无需原生驱动)
如果不想引入pg-native,可以在连接配置里自定义类型解析规则,把字符串转成对应的数值类型:
const Sequelize = require('sequelize'); const { types } = require('pg'); const sequelize = new Sequelize('your_db', 'user', 'password', { host: 'localhost', dialect: 'postgres', dialectOptions: { types: { // 把PostgreSQL的INT8(大整数)解析为JavaScript Number INT8: types.getTypeParser(types.builtins.INT8)(val => parseInt(val, 10)), // 把NUMERIC/DECIMAL解析为JavaScript Number NUMERIC: types.getTypeParser(types.builtins.NUMERIC)(val => parseFloat(val)), // 其他需要修复的类型(比如INT4、FLOAT8)可以按需添加 } } });
二、临时方案:测试阶段兼容类型差异
如果暂时没法修改Sequelize配置,又不想逐个字段解析,可以用自定义匹配逻辑来绕开类型校验:
1. 写个类型转换辅助函数
针对测试场景,写一个函数把返回对象的字符串类型数值转成数字,再用toMatchObject校验:
function convertDbResponseTypes(dbObj) { const converted = { ...dbObj }; // 按需转换字段,比如id、price等 if (converted.id) converted.id = parseInt(converted.id, 10); if (converted.price) converted.price = parseFloat(converted.price); return converted; } // 测试时使用 expect(convertDbResponseTypes(yourDbResult)).toMatchObject(yourExpectedObj);
2. 通用自动转换匹配函数
如果字段较多,可以写一个更通用的函数,根据预期对象的类型自动转换实际值:
function expectToMatchWithTypeConversion(actual, expected) { const convertedActual = { ...actual }; Object.keys(expected).forEach(key => { // 如果预期是数字,实际是字符串,尝试转换 if (typeof expected[key] === 'number' && typeof convertedActual[key] === 'string') { const numVal = parseFloat(convertedActual[key]); convertedActual[key] = isNaN(numVal) ? convertedActual[key] : numVal; } }); expect(convertedActual).toMatchObject(expected); } // 调用方式 expectToMatchWithTypeConversion(yourDbResult, yourExpectedObj);
总结
优先推荐根源修复的两种方法,这样后续所有业务代码和测试都不用再处理类型问题;如果是紧急测试需求,用辅助函数可以快速搞定匹配问题。
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

