Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec: Check if array includes object which includes property

I have a json array full of objects.

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

I need to see if the array holds an object which contains an attribute "id" that is set to 5. The "name" attribute is unknown.

How do I do this in rspec?

I know if I had the name attribute I know I could just do:

my_array.should include({:id => 5, :name => "jim"}) 
like image 368
Jordan Ell Avatar asked Dec 18 '13 19:12

Jordan Ell


4 Answers

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

or with the legacy should syntax

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

Please note that myArray is not following Ruby conventions. Variables use underscore

my_array

not camelcase

myArray
like image 50
Simone Carletti Avatar answered Nov 07 '22 13:11

Simone Carletti


It is also possible using the having_attributes alias:

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

or, as in my own use case, matching the whole array:

expect(my_array).to contain_exactly(
  an_object_having_attributes(id: 5),
  an_object_having_attributes(id: 6),
  an_object_having_attributes(id: 2)
)
like image 27
tom-in-dk Avatar answered Nov 07 '22 13:11

tom-in-dk


You can unfold an array and to check matching of two arrays like here:

expect(my_array).to include(*compare_array) 

It'll unfold and match each value of array.

It's equivalent to this:

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

Source: Relish documentation

like image 24
ilgam Avatar answered Nov 07 '22 13:11

ilgam


This would only be worth it if you were doing many of these, but you could define a 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)
like image 3
Ash Wilson Avatar answered Nov 07 '22 12:11

Ash Wilson