I have a method which performs some actions on Cat model and in case of incorrect input raises an exception:
context "hungry cat" do it { expect { eat(what: nil) }.to raise_error } end
What I want to do is to check whether this method change cats status, like that:
context "hungry cat" do it { expect { eat(what: nil) }.to raise_error } it { expect { eat(what: nil) }.not_to change(cat, :status) } end
The problem is that since eat(what: nil)
will raise an exception the second it
will fail no matter what. So, is it possible to ignore exception and check some condition?
I know that it's possible to do something like:
it do expect do begin eat(what: nil) rescue end end.not_to change(cat, :status) end
But it's way too ugly.
rspec-expectations ships with a number of built-in matchers. Each matcher can be used. with expect(..). to or expect(..). not_to to define positive and negative expectations.
Ruby actually gives you the power to manually raise exceptions yourself by calling Kernel#raise. This allows you to choose what type of exception to raise and even set your own error message. If you do not specify what type of exception to raise, Ruby will default to RuntimeError (a subclass of StandardError ).
Summary: RSpec's subject is a special variable that refers to the object being tested. Expectations can be set on it implicitly, which supports one-line examples. It is clear to the reader in some idiomatic cases, but is otherwise hard to understand and should be avoided.
You can chain positive assertions with and
. If you want to mix in a negated one in the chain, RSpec 3.1 introduced define_negated_matcher
.
You could do something like:
RSpec::Matchers.define_negated_matcher :avoid_changing, :change expect { eat(what: nil) } .to raise_error .and avoid_changing(cat, :status)
Inspired by this comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With