2013-12-18 193 views
11

我有一个充满对象的json数组。Rspec:检查数组是否包含包含属性的对象

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

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

如何在rspec中执行此操作?

我知道,如果我有属性的名称,我知道我可能只是这样做:

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

回答

22
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 

没有驼峰

myArray 
+0

教导正确的Ruby命名约定的奖励积分。好样的! –

+0

对于任何正在寻找RSpec 3解决方案的人来说,查看RSpecs新的可组合匹配器。 –

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) 
0

这里的客户匹配器“include_object”(可能应该使用更好的名称,因为它只是检查ID是否存在)

使用如下

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

匹配器可以处理对象,Hashs(符号或字符串) 它还版画只是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 
1

认沽这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 

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

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

您可以展开一个数组,并检查两个数组的匹配喜欢这里:

expect(my_array).to include(*compare_array) 

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

这是相同的:

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

来源:Relish documentation

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