【问题标题】:How to compare hash containing array but ignoring order inside the array如何比较包含数组的哈希但忽略数组内的顺序
【发布时间】:2021-09-08 22:12:46
【问题描述】:

在我的规范中,我有以下响应结构

something: { foo: [{bar: 'baz'}, {one: 'two'}] }

我尝试比较它,但 foo-array 内部的顺序是随机的。 我找到了这篇文章: link,其中有如下代码:

当你有一个数组但不能确定元素的顺序时使用 a_collection_containing_exactly

expected = {
  "data" => a_collection_containing_exactly(
    a_hash_including("id" => "1"),
    a_hash_including("id" => "2")
  )
}
expect(response.parsed_body).to include(expected)

但这对我不起作用,因为比较将匹配器 a_collection_containing_exactly 视为哈希的一部分

{"base_matcher"=>{"expected"=>[{bar: 'baz'}, {one: 'two'}]}}

我错过了什么?有没有更好的解决方案?

编辑: 为了澄清,这是一个最小的可重现示例

expected_value = { something: { foo: [{ bar: 'baz' }, { one: 'two' }] }}

expect(response.parsed_body).to eq(expected_value)

【问题讨论】:

  • 您发布了文章中的代码,但是您的 RSpec 代码是什么样的?你能提供一个minimal reproducible example吗?
  • @J.Krzus :什么是散列数组?您发布的副本包含哈希,但不存在数组。
  • @user1934428 我添加了更多代码以进行澄清。但我已经找到了解决方案。

标签: ruby-on-rails ruby rspec


【解决方案1】:

我认为 RSpec match_array 匹配器是您所需要的:

array_of_hashes = [{bar: "baz"},{one: "two"}]

expect(response.parsed_body[:foo]).to match_array(array_of_hashes)

如果您的顶级哈希有很多键,您可以编写自定义匹配器:

# in spec/matchers/match_sort_indifferent.rb:

require 'rspec/expectations'

RSpec::Matchers.define :match_sort_indifferent do |expected|
  match do |actual|
    expected.keys.each do |key|
      expect(actual[key]).to match_array expected[key]
    end
    expect(expected.keys.length).to eq actual.keys.length
  end
end


# in spec/models/test_spec.rb

require 'rails_helper'
require 'matchers/match_sort_indifferent'

result = {foo: [{bar: "baz"},{qux: "dak"}]}

describe {
  it {
    expect(result).to match_sort_indifferent({foo: [{qux: "dak"},{bar: "baz"}]})
    expect(result).not_to match_sort_indifferent({foo: [{qux: "sum"},{bar: "baz"}]})
  }
}

【讨论】:

  • 这是一个很好的答案,但我没有足够澄清。我想验证整个响应,并且在 ':foo' 级别有更多键,它们是哈希值。单独检查数组看起来不太优雅,这就是为什么我正在寻找一种方法来在一个匹配中检查它
【解决方案2】:

感谢您的回答。我在 Rspec-json-expectations gem 和 UnorderedArray 的帮助下解决了这个问题

所以我的解决方案如下所示:

expected_value = { something: { foo: UnorderedArray({ bar: 'baz' }, { one: 'two' }) }}

和匹配器

expect(response.parsed_body).to include_json expected_value

缺点是它只检查预期值是否存在,而不会捕获额外的值。

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    相关资源
    最近更新 更多