我正在编写rails的集成测试,我想比较用发送的JSON对象创建的对象。返回的对象与发送的对象不完全相同,(即)它具有对象发送的密钥,因为我使用活动模型序列化器来提取返回对象中的关联。基本上,我只想比较两个对象之间的所有相同的键,看它是否相同。如果有一个干净,高效的代码片段可以帮我这么做!
答案 0 :(得分:2)
“聪明”测试代码很少有用。每个测试应该尽可能简单,它应该测试某个对象的行为而不是它的组成。但总有办法聪明。
一种难以理解的聪明方法是使用Array#&来查找键的交集,然后查找值之间的相等性。这将在相对平坦的哈希上工作。例如:
hash1 = {:key1=>"value1", :key2=>"value2", :key3=>"value3", :key4=>"value4"}
hash2 = {:key1=>"value1", :key2=>"value2", :key5=>"value5"}
Array(hash1.keys & hash2.keys).map { |k| hash1[k] == hash2[k] }.uniq
#=> [true]
如果你正在使用RSpec进行测试,你可以这样说:
it 'has some matching key/value pairs' do
# ... populate hash1
# ... populate hash2
Array(hash1.keys & hash2.keys).
map { |k| hash1[k] == hash2[k] }.uniq.should == [true]
end
当然,如果期望是假的,那么你就不会真正知道原因,或者哪个键/值对错了。这只是您应该始终使用固定输入和输出进行测试的众多原因之一,而不是尝试进行动态比较。
答案 1 :(得分:0)
首先,找到两个哈希包含的键,然后比较这些键的值:
hash1 = {:key1 => "value1", :key2 => "value2", :key3 => "value3", :key4 => "value4"}
hash2 = {:key1 => "value1", :key2 => "value2", :key5 => "value5"}
hash1_keys = hash1.keys
hash2_keys = hash2.keys
comparable_keys = hash1_keys.select{|key| hash2_keys.include?(key)}
comparable_keys.each do |key|
hash1[key].should == hash2[key]
end
答案 2 :(得分:0)
您可以使用Hash#slice
,这是一个Active Support核心扩展程序。
例如,如果要检查的密钥为:a, :b, :c
,但结果包含:a, :b, :c, :d
,则slice
会将结果缩小为仅包含您关注的密钥:
expected = { :a => 1, :b => 2, :c => 3 }
result = { :a => 1, :b => 2, :c => 3, :d => 4 }
result.slice(:a, :b, :c) == expected
# => true
如果您收到NoMethodError: undefined method 'slice'
例外,则需要active_support/core_ext/hash/slice