Angular/Jasmine测试报错:预期抛出字符串却抛出Error对象
问题描述
我正在使用Angular/Jasmine运行测试,以下是我的验证函数:
ValidateX(value : number) { if (value > 5) { throw new Error('Number is greater than 5'); } }
对应的测试代码:
it('X test', () => { expect(function(){service.ValidateX(7);}).toThrow('Number is greater than 5'); })
运行测试后得到如下错误:
ValidationsService > X test
Expected function to throw 'Number is greater than 5', but it threw Error: Number is greater than 5.
at
at UserContext.apply (http://localhost:9876/karma_webpack/webpack:/src/app/services/validations.service.spec.ts:27:47)
at _ZoneDelegate.invoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:369:28)
at ProxyZoneSpec.onInvoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:2081:39)
at _ZoneDelegate.invoke (http://localhost:9876/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:368:34)*
我已经检查过错误信息没有多余空格,也尝试过在函数里给错误信息加引号,都没用。错误信息看起来完全一致,但测试就是不通过,请问我忽略了什么?
问题原因与解决方案
问题出在Jasmine的toThrow匹配器的用法逻辑上:
- 当你给
toThrow传入字符串参数时,它会严格对比抛出对象的toString()返回值,而非错误对象的message属性。 - 你的代码抛出的是
Error实例,它的toString()结果是Error: Number is greater than 5,但测试里传入的是纯字符串'Number is greater than 5',两者不匹配,导致测试失败。
有两种可行的解决办法:
- 使用
toThrowError匹配错误消息:这个匹配器专门用来校验错误对象的message属性,直接传入消息字符串即可:
it('X test', () => { expect(() => service.ValidateX(7)).toThrowError('Number is greater than 5'); })
- 用
toThrow匹配完整Error对象或类型:如果坚持使用toThrow,可以选择传入Error实例或者构造函数:
// 方式一:传入Error实例,完全匹配错误类型和消息 it('X test', () => { expect(() => service.ValidateX(7)).toThrow(new Error('Number is greater than 5')); }) // 方式二:传入Error构造函数,仅验证错误类型(不校验消息) it('X test', () => { expect(() => service.ValidateX(7)).toThrow(Error); })
另外,推荐用箭头函数替代普通函数作为expect的参数,写法更简洁直观。
内容的提问来源于stack exchange,提问作者Douglas Hahn

