2013-05-31 11 views
21

Ich habe eine Methode, die einige Aktionen auf Cat Modell und bei falscher Eingabe führt eine Ausnahme auslöst:Wie erwarte ich etwas, das in RSpec eine Ausnahme auslöst?

context "hungry cat" do 
    it { expect { eat(what: nil) }.to raise_error } 
end 

Was ich tun möchte, ist, ob diese Methode ändern Katzen-Status zu überprüfen, wie folgt aus:

context "hungry cat" do 
    it { expect { eat(what: nil) }.to raise_error } 
    it { expect { eat(what: nil) }.not_to change(cat, :status) } 
end 

das Problem ist, dass seit eat(what: nil) eine Ausnahme erhöhen die zweite it wird umhin, egal was passiert. Also, ist es möglich, Ausnahmen zu ignorieren und einige Bedingungen zu überprüfen?

Ich weiß, dass es möglich ist, wie etwas zu tun:

it do 
    expect do 
    begin 
     eat(what: nil) 
    rescue 
    end 
    end.not_to change(cat, :status) 
end 

Aber es ist viel zu hässlich.

+2

Wie wäre es 'es {erwarten {essen (was: null) Rettung nil} .not_to Änderung (Katze,: Status)}'? – awendt

+0

@awendt gut, könnten Sie es als Antwort posten? – Andrew

+0

In 'Test/unit', gibt es eine schöne Behauptung ist,' assert_raise', glaube ich. –

Antwort

18

Sie könnten die "Rettung nil" Idiom verwenden zu verkürzen, was Sie bereits haben:

it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) } 
+4

Dies funktioniert, aber ich wünschte, es gäbe einen rspec Weg dies zu tun, zB: 'expect {...} .ignoring_errors.to change (cat,: Status) ' –

0

Es klingt seltsam, dass der eat(what: nil) Code nicht für jede Ihrer Tests in Isolation ausgeführt wird und die anderen auswirkt. Ich bin mir nicht sicher, aber vielleicht, wenn ich die Tests etwas neu schreibe, wird entweder das Problem gelöst oder genauer gesagt, wo das Problem liegt (wählen Sie unten Ihren Geschmack).

Mit should:

context "hungry cat" do 
    context "when not given anything to eat" do 
    subject { -> { eat(what: nil) } } 
    it { should raise_error } 
    it { should_not change(cat, :status) } 
    end 
end 

Mit expect:

context "hungry cat" do 
    context "when not given anything to eat" do 
    let(:eating_nothing) { -> { eat(what: nil) } } 
    it "raises an error" do 
     expect(eating_nothing).to raise_error 
    end 
    it "doesn't change cat's status" do 
     expect(eating_nothing).to_not change(cat, :status) 
    end 
    end 
end 
+0

Ich glaube, Sie die Frage falsch verstanden. Wenn "essen" eine Ausnahme auslöst, wird der zweite Fall immer fehlschlagen, weil die Ausnahme nicht übergeben wird. – Andrew

+0

Vielleicht habe ich es getan. Ist das erwartete Verhalten in Ihrem System nicht behandelte Ausnahmen, die Ihre Benutzer potenziell generieren können? Wenn ja, könntest du erklären, warum, entweder hier oder in einer Bearbeitung deiner Frage? –

+0

Ja, ist es natürlich das erwartete Verhalten zudem die meisten Ruby-Bibliotheken können Ausnahmen erzeugen, die von ihren Nutzern und dieses Verhalten behandelt werden sollte sollte auch getestet werden. Z.B. rails '#save!', 'Float ('aaa')', EOFError während 'File # read'. Was ich in meinem Fall testen möchte, ist, dass der Kontext erfolgreich wiederhergestellt wurde, nachdem eine Ausnahme ausgelöst wurde (Transaktion wurde zurückgesetzt, Deskriptoren geschlossen usw.). – Andrew

12

In RSpec 3 Sie können die beiden Tests zu einem zusammenfassen. Ich finde dies besser lesbar als der rescue nil Ansatz.

it { expect { eat(what: nil) }.to raise_error.and not_to change(cat, :status)}

+4

Sind Sie sicher, dass dies die richtige Syntax ist? Es gibt mir einen Fehler: 'NoMethodError: undefined Methode 'not_to' für # dombesz

+1

Nein, das wird nicht funktionieren, siehe meinen Kommentar unten. –

11

Sie können chain positive Behauptungen mit and. Wenn Sie in einem negierten in der Kette mischen möchten, RSpec 3.1 define_negated_matcher eingeführt.

Man könnte so etwas wie tun:

RSpec::Matchers.define_negated_matcher :avoid_changing, :change 

expect { eat(what: nil) } 
    .to raise_error 
    .and avoid_changing(cat, :status) 

Inspiriert von this comment.

+1

Das ist wirklich großartig, danke. Ich kann nicht glauben, dass ich nicht schon einmal darauf gestoßen bin. – adaam

+1

Das sollte die gute Antwort sein! –

Verwandte Themen