RSpec中hash_including匹配不符合预期问题排查
嘿,我帮你找到了测试断言失败的核心原因,咱们一步步来看:
问题回顾
API返回的JSON响应
{ "data": { "someFunction": null }, "errors": [ { "message": "Email was already confirmed, please try signing in", "locations": [ { "line": 9, "column": 2 } ], "path": [ "someFunction" ], "extensions": { "code": "USER_ERROR" } } ] }
你编写的测试断言
expect(json_response[:errors]).to contain_exactly( hash_including( message: "Email was already confirmed, please try signing in.", extensions: { code: 'USER_ERROR' } ) )
测试失败提示
expected collection contained: [hash_including(:message=>"Email was already confirmed, please try signing in.", :extensions=>{:code=>"USER_ERROR"})]
actual collection contained: [{:extensions=>{:code=>"USER_ERROR"}, :locations=>[{:column=>9, :line=>2}], :message=>"Email was already confirmed, please try signing in", :path=>["someFunction"]}]
the missing elements were: [hash_including(:message=>"Email was already confirmed, please try signing in.", :extensions=>{:code=>"USER_ERROR"})]
the extra elements were: [{:extensions=>{:code=>"USER_ERROR"}, :locations=>[{:column=>9, :line=>2}], :message=>"Email was already confirmed, please try signing in", :path=>["someFunction"]}]
错误根源
你仔细对比断言里的message和实际响应的message,会发现只差了一个末尾的句号!
- 断言中的message:
"Email was already confirmed, please try signing in."(最后有个.) - 实际响应的message:
"Email was already confirmed, please try signing in"(最后没有.)
字符串匹配是完全精确的,哪怕只差一个标点符号都会导致hash_including判断不匹配,进而让整个断言失败。
修复方案
只需要把断言里message末尾的句号去掉,和实际响应保持一致即可:
expect(json_response[:errors]).to contain_exactly( hash_including( message: "Email was already confirmed, please try signing in", extensions: { code: 'USER_ERROR' } ) )
另外补充个小技巧:因为你的错误数组里只有一个元素,也可以用include来简化断言,效果完全相同,写法更简洁:
expect(json_response[:errors]).to include( hash_including( message: "Email was already confirmed, please try signing in", extensions: { code: 'USER_ERROR' } ) )
内容的提问来源于stack exchange,提问作者aarona

