Rspec:检查数组是否包含包含属性的对象

时间:2013-12-18 19:49:32

标签: ruby-on-rails ruby arrays rspec

我有一个充满对象的json数组。

my_array = [{id => 6, name => "bob"}, 
           {id => 5, name => "jim"}, 
           {id => 2, name => "steve"}]

我需要查看数组是否包含一个包含属性“id”的对象,该属性设置为5.“name”属性未知。

我如何在rspec中执行此操作?

我知道如果我知道我可以做的名字属性:

my_array.should include({:id => 5, :name => "jim"}) 

7 个答案:

答案 0 :(得分:23)

expect(myArray.find { |item| item[:id] == 5 }).to_not be_nil

或遗留应用语法

myArray.find { |item| item[:id] == 5 }.should_not be_nil

请注意,myArray不符合Ruby惯例。变量使用下划线

my_array

不是camelcase

myArray

答案 1 :(得分:3)

如果您正在执行其中的许多操作,这只会是值得的,但您可以定义custom matcher

RSpec::Matchers.define :object_with_id do |expected|
  match do |actual|
    actual[:id] == expected
  end
  description do
    "an object with id '#{expected}'"
  end
end

# ...

myArray.should include(object_with_id 5)

答案 2 :(得分:2)

也可以使用hading_attributes别名:

expect(my_array).to include( an_object_having_attributes(id: 5) )

或者,就像我自己的用例一样,匹配整个数组:

expect(my_array).to contain_exactly(
  an_object_having_attributes(id: 5),
  an_object_having_attributes(id: 6),
  an_object_having_attributes(id: 2)
)

答案 3 :(得分:1)

将此Nth-latest.bat "C:\somewhere" 2 匹配器放入any,并在spec/support/matchers.rb

中提出要求
spec_helper.rb

然后你可以在这样的例子中使用它:

RSpec::Matchers.define :any do |matcher|
  match do |actual|
    actual.any? do |item|
      matcher.matches?(item)
    end
  end
end

答案 4 :(得分:1)

您可以展开数组并检查两个数组的匹配,如下所示:

expect(my_array).to include(*compare_array) 

它将展开并匹配数组的每个值。

它等同于:

expected([1, 3, 7]).to include(1,3,7)

来源:Relish documentation

答案 5 :(得分:0)

这是一个客户匹配器" include_object" (可能应该使用更好的名称,因为它只检查id是否存在)

使用如下

obj = {id:1}
objs = [{id: 1}, {id: 2}, {id: 3}]
expect(objs).to include_object obj

匹配器可以处理对象,哈希(符号或字符串) 它还会在异常中打印出数组中的id,以便于查看

RSpec::Matchers.define :include_object do |expected|
  ids = []
  match do |actual|
    ids = actual.collect { |item| item['id'] || item[:id] || item.id }

    ids.find { |id| id.to_s == expected.id.to_s }
  end

  failure_message_for_should_not do |actual|
    "expected that array with object id's #{ids} would contain the object with id '#{expected.id}'"
  end

  failure_message_for_should_not do |actual|
    "expected that array with object id's #{ids} would not contain the object with id '#{expected.id}'"
  end
end

答案 6 :(得分:0)

我会像这样使用RSpec 3的可组合include匹配器:

expect(my_array).to include(include(id: 5))

如果失败,这将通过RSpec获得更详细的输出。

it 'expects to have element with id 3' do
  my_array = [
    { id: 6, name: "bob" },
    { id: 5, name: "jim" },
    { id: 2, name: "steve" }
  ]
  expect(my_array).to include(include(id: 3))
end

这将生成以下失败消息:

Failures:

  1) Test expects to have element with id
     Failure/Error: expect(my_array).to include(include(id: 3))

       expected [{:id => 6, :name => "bob"}, {:id => 5, :name => "jim"}, {:id => 2, :name => "steve"}] to include (include {:id => 3})
       Diff:
       @@ -1,2 +1,2 @@
       -[(include {:id => 3})]
       +[{:id=>6, :name=>"bob"}, {:id=>5, :name=>"jim"}, {:id=>2, :name=>"steve"}]

进一步阅读:

https://relishapp.com/rspec/rspec-expectations/docs/composing-matchers