Crystal specs测试哈希相等性时输出格式不符问题如何解决
Crystal Spec哈希相等性断言失败修复方案
问题现象
编写Crystal specs测试用例验证哈希相等性时,断言失败输出分两种情况:
- 哈希键为Symbol类型时:
Expected: {text: "Hello World"} got: {:text => "Hello World"}
- 哈希键为String类型时:
Expected: {text: "Hello World"} got: {"text" => "Hello World"}
目标是让返回值匹配{text: "Hello World"}格式,顺利通过eq相等性断言。
现有实现代码
- Symbol键版本:
@output = {} of Symbol => Output @output[name] = @buffer # name是Symbol类型 language.parse("Hello World").should eq({ text: "Hello World" })
- String键版本:
@output = {} of String => Output @output[name.to_s] = @buffer # name是Symbol类型
问题根因
Crystal语法中,{text: "Hello World"}的短写法构造的是NamedTuple(命名元组),不是Hash类型。
无论键是Symbol还是String,Hash的标准字面量格式为{:key => value}或{"key" => value},和NamedTuple属于完全不同的类型,类型不匹配时eq断言必然失败,和输出打印格式无关。
修复方案
根据实际业务需求二选一即可:
方案1:调整业务代码返回NamedTuple(匹配现有测试写法)
如果业务场景不需要动态增删键、键集合固定,直接返回NamedTuple即可通过断言:
# 固定键场景直接构造 @output = {text: @buffer} # 动态键场景用NamedTuple.new构造 @output = NamedTuple.new(name => @buffer) # name为Symbol类型 language.parse("Hello World").should eq({ text: "Hello World" }) # 断言通过
方案2:调整测试断言匹配Hash类型
如果业务场景必须用Hash(比如需要动态增删键、键集合不固定),修改测试中的预期值为对应类型的Hash字面量即可:
- 业务代码用Symbol作为Hash键时,测试改为:
language.parse("Hello World").should eq({:text => "Hello World"})
- 业务代码用String作为Hash键时,测试改为:
language.parse("Hello World").should eq({"text" => "Hello World"})
注意:不要尝试通过修改对象打印格式绕过断言,类型不一致时值比较不会相等。
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

