2013-12-18 6 views
11

Ich habe ein JSON-Array voller Objekte.Rspec: Überprüfen, ob das Array ein Objekt mit der Eigenschaft enthält

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

Ich muss sehen, ob das Array ein Objekt hält, die ein Attribut „id“ enthält, die bis 5. Das Attribut „name“ ist unbekannt gesetzt.

Wie mache ich das in rspec?

Ich weiß, wenn ich den Namen hatte Attribut Ich weiß, ich konnte einfach tun:

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

Antwort

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

oder mit der Legacy-Syntax sollte

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

Bitte beachten Sie, dass myArray Ruby nicht folgt Konventionen. Variablen verwenden

my_array 

unterstreichen Camelcase nicht

myArray 
+0

Bonuspunkte für die richtigen Ruby-Namenskonventionen zu unterrichten. Bravo! –

+0

Für alle, die eine Lösung mit RSpec 3 suchen. Schauen Sie sich RSpecs neue Composable Matcher an. –

3

Dies ist nur wert sein würde, wenn Sie viele von ihnen taten, aber man konnte eine custom matcher definieren:

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

Hier ein Kunden-Matcher "include_object" (wahrscheinlich sollte ein besserer Name verwendet werden, da er nur prüft, ob die IDs vorhanden sind)

wie folgt verwendet

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

Matcher können für ein leichteres Ablesen

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

Put Objekt, Hashs (Symbole oder string) Es auch druckt nur die IDs in der Anordnung auf Ausnahme behandeln dies any Matcher in spec/support/matchers.rb und benötigen es in Ihrem spec_helper.rb

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

Dann können Sie es in den Beispielen wie folgt verwenden:

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

Sie ein Array entfalten kann und wie hier Abgleich von zwei Arrays zu überprüfen:

expect(my_array).to include(*compare_array) 

Es wird sich entfalten und Spiel jeder Wert von Array.

es dazu äquivalent ist:

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

Quelle: Dies hätte den Vorteil einer mehr

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

: Relish documentation

0

ich die RSpec 3 ist zusammensetzbare include Matcher wie so verwenden würde ausführliche Ausgabe über RSpec im Falle eines Fehlers.

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 

Dies würde folgende Fehlermeldung erzeugen:

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"}] 

Weiterführende Literatur:

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

Verwandte Themen