Node.js Jest单元测试断言Error对象引号不匹配问题排查
Jest 断言异步Error对象失败解决方案
问题根因
- 断言失败和Jest输出的外层双引号无关:双引号是Jest控制台对字符串类型值的格式标记,不是预期值本身的内容。核心问题是你用
toBe做严格相等判断时,一侧是字符串,另一侧是ConnectionError类型的Error实例,二者类型不同,永远不可能相等。 - 调用
err.toString()/err.message触发TS的Object is of type unknown报错,是因为TypeScript中catch块捕获的错误默认类型为unknown,不允许直接访问unknown类型值的属性或方法。 .toThrow不生效是用法错误:该匹配器默认匹配同步抛出的错误,匹配异步reject时需要搭配rejects使用,你之前直接传入已触发的异步Promise,没有走正确的异步断言流程,自然匹配不到错误。
可直接复用的正确写法
写法1:无try/catch 推荐写法
不需要手动捕获错误,直接用Jest内置的异步错误匹配器,记得给整个断言加await:
describe('aresFileCopier', () => { test('log error', async () => { await registerDB('ares-test', { client: 'mssql', connection: { host: 'test-mssql', database: 'master', user: 'BAD_USER', password: 'BAD_Password', port: 1433, }, }); // 仅匹配错误信息 await expect( exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO') ).rejects.toThrow('Login failed for user \'BAD_USER\'.'); // 如果需要同时匹配错误码、错误类型等更多属性,用toMatchObject await expect( exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO') ).rejects.toMatchObject({ code: 'ELOGIN', message: 'Login failed for user \'BAD_USER\'.' }); await shutdown(); }); });
写法2:手动try/catch 写法
如果需要自定义错误处理逻辑,先对捕获的err做类型断言,再访问属性,同时要加断言确保Promise确实走到了reject分支,避免用例假通过:
// 如果你项目里有导出tedious的ConnectionError类型可以直接导入,没有的话可以临时定义类型,或者直接断言为Error import { ConnectionError } from 'tedious/lib/errors'; describe('aresFileCopier', () => { test('log error', async () => { await registerDB('ares-test', { client: 'mssql', connection: { host: 'test-mssql', database: 'master', user: 'BAD_USER', password: 'BAD_Password', port: 1433, }, }); try { await exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO'); // 走到这里说明Promise没有reject,用例直接失败 throw new Error('Expected exec method to throw login error, but it resolved successfully'); } catch(err) { const loginErr = err as ConnectionError; expect(loginErr.message).toBe('Login failed for user \'BAD_USER\'.'); expect(loginErr.code).toBe('ELOGIN'); } await shutdown(); }); });
避坑提示
- 不要尝试修改Jest控制台的输出格式,外层双引号只是类型标识,修改控制台输出对断言逻辑没有任何帮助。
- 所有带
rejects/resolves的异步断言必须加await,否则Jest不会等待异步逻辑执行完成,会出现用例假通过的问题。 - 你贴出的
exec方法直接返回Promise,不需要额外包装,直接传入expect()即可。
内容的提问来源于stack exchange,提问作者ritvik seth
相关产品推荐
相关产品推荐

