-1

我正在为 rails 编写集成测试,我想将创建的对象与发送的 JSON 对象进行比较。返回的对象与发送的对象不完全相同,(即)它具有发送的对象没有的键,因为我使用活动模型序列化程序来提取返回对象中的关联。基本上,我只想比较两个对象之间所有相同的键,看看它是否相同。让我知道是否有一个干净有效的代码片段可以为我做到这一点!

4

3 回答 3

2

TL;博士

“聪明”的测试代码很少有用。每个测试都应该尽可能简单,并且应该测试某个对象的行为而不是其组成。不过,总有办法变得聪明。

使用数组交集

一种难以理解的聪明方法是使用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

当然,如果期望是错误的,那么您将不会真正知道为什么,或者哪个键/值对是错误的。这只是您应该始终使用固定输入和输出进行测试而不是尝试进行动态比较的众多原因之一。

于 2013-08-26T23:11:21.063 回答
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
于 2013-08-26T22:02:05.137 回答
0

您可以使用Hash#slice,这是一个 Active Support 核心扩展。

例如,如果您要检查的键是:a, :b, :c,但结果包含:a, :b, :c, :dslice则会将结果缩减为仅包含您关心的键:

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

于 2013-08-26T22:25:09.277 回答