44

Cat モデルでいくつかのアクションを実行するメソッドがあり、入力が正しくない場合は例外が発生します。

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

私がやりたいことは、このメソッドが猫のステータスを変更するかどうかを確認することです。

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

問題はeat(what: nil)、例外が発生するため、2番目の例外がit何があっても失敗することです。では、例外を無視して何らかの条件をチェックすることは可能ですか?

次のようなことができることを知っています:

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

しかし、それはあまりにも醜いです。

4

5 に答える 5

43

で肯定的なアサーションを連鎖させることができますand。チェーンに否定されたものを混ぜたい場合は、RSpec 3.1 で導入されましdefine_negated_matcherた。

次のようなことができます。

RSpec::Matchers.define_negated_matcher :avoid_changing, :change

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

このコメントに触発されました。

于 2016-11-30T07:42:34.293 に答える
41

You could use the "rescue nil" idiom to shorten what you already have:

it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) }
于 2013-06-03T11:21:06.150 に答える
9

RSpec 3 では、2 つのテストをチェーンして 1 つにすることができます。rescue nilこれはアプローチよりも読みやすいと思います。

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

于 2014-09-30T03:43:29.137 に答える
0

eat(what: nil)コードがテストごとに分離して実行されず、他のテストに影響を与えているのは奇妙に思えます。よくわかりませんが、おそらくテストを少し書き直すと、問題が解決するか、問題がどこにあるかをより正確に特定できます (以下のフレーバーを選択してください)。

使用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

使用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
于 2013-06-01T02:38:13.807 に答える