I would like to compare the keys I get back in a JSON response for all results against a pre defined array of keys.
So I have this set of keys
def key_array
["key1", "key2", "key3"]
end
My response from an api call is returned in this format (array of hashes) outputted from @response
{"0"=>
{"key1"=>"value1",
"key2"=>"value2",
"key3"=>"value3"},
"1"=>
{"key1"=>"value1",
"key2"=>"value2",
"key3"=>"value3"},
"2"=>
{"key1"=>"value1",
"key2"=>"value2",
"key3"=>"value3"},
"Status"=>"100"}
}
When I do @response.keys
I get
["0", "1", "2"]
I can access each set of keys via its index individually with @response["0"].keys
, for example will return
["key1", "key2", "key3"]
What I would like to do with the rspec matchers is check that every returned result from the api call has the keys set in key_array
At the moment
expect(@response.keys).to match_array(key_array)
is matching the array of indexes against the key_array
I have stored. How do I access the keys from within each index?
@response.each_value do |value|
expect(value.keys).to match_array(key_array)
end
This will work for you.
required_keys = %w{key1 key2 key3}
@response.each do |key, hash|
next if (key == "Status")
expect(hash).to include(*required_keys)
end
You can add an optional message to see which index any failure occured on:
@response.each do |key, hash|
next if (key == "Status")
expect(hash).to include(*required_keys), "Failed at #{key}"
end
The next
check can be turned into a regular-expression check, in case you've got other non-numeric keys that you want to ignore eg
next if /\D/.match(key) # the \D matches non-digits
If you want call expect method only once, you can do
expect( @response.values.map{|h| h.keys.sort}.uniq ).to eq([%w(key1 key2 key3)])
however it is rather ugly approach
I would firstly harvest incompletes:
incompletes = @response.reduce([]) { |memo, kv|
(key_array - kv.last.keys).empty? ? memo : memo << kv.first
}
And then do checks:
expect(incompletes).to match_array([])
Whether you only need to check:
incompletes = @response.reject { |*kv| (key_array - kv.last.keys).empty? }
expect(incompletes).to match_array([])
This former approach makes it easy to collect any desired information about wrong entries, since you are free to put anything valuable in the resulting array. Hope it helps.
UPD With status:
incompletes = @response.reject { |k,v|
# ⇓⇓ is k integer? ⇓⇓ or ⇓⇓ are valid keys all presented? ⇓⇓
k.to_i.to_s != k || (key_array - v.keys).empty?
}
expect(incompletes).to match_array([])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.