Reputation: 914
I'm trying to make sure certain data has remain unchanged by a single action:
expect {
# running migration and user reload here
}.not_to change(user, :avatar_url).from(sample_avatar_url).and change(user, :old_avatar).from(nil)
sample_avatar_url
is a string defined in the beginning of the spec file.
Basically, I want to check whether the avatar_url
and old_avatar
remain untouched by what's happening in the expect
block.
The output from the above code is:
expect(...).not_to matcher.and matcher
is not supported, since it creates a bit of an ambiguity. Instead, define negated versions of whatever matchers you wish to negate withRSpec::Matchers.define_negated_matcher
and useexpect(...).to matcher.and matcher
.
Upvotes: 25
Views: 14588
Reputation: 11
i know it is long ago but i had a similar problem and did something like this:
expect {
# running migration and user reload here
}.not_to change { user.slice(:avatar_url, :old_avatar) }
Upvotes: 1
Reputation: 7272
As stated in Thomas answer, it does not work because it's not clear reading and you can create a negated matcher. Another option is to use the saharspec gem and its dont
matcher negation.
Here is an extract from the project's README:
Another (experimental) attempt to get rid of
define_negated_matcher
.dont
is not 100% grammatically correct, yet short and readable enought. It just negates attached matcher.# before RSpec.define_negated_matcher :not_change, :change it { expect { code }.to do_stuff.and not_change(obj, :attr) } # after: no `define_negated_matcher` needed require 'saharspec/matchers/dont' it { expect { code }.to do_stuff.and dont.change(obj, :attr) }
So you can write your expectation without creating a negated matcher like this:
expect {
# running migration and user reload here
}.to dont.change(user, :avatar_url).from(sample_avatar_url).and
dont.change(user, :old_avatar).from(nil)
Upvotes: 0
Reputation: 49950
This doesn't work because it's not clear reading whether thats supposed to mean not change the first and not change the second, or not change the first but change the second. You have a couple of options to get around this
Since you're checking static values just don't use change
..run migration and user reload..
expect(user.avatar_url).to eq(sample_avatar_url)
expect(user.old_avatar).to eq nil
or use define_negated_matcher to create a not_change matcher
RSpec::Matchers.define_negated_matcher :not_change, :change
expect {
# running migration and user reload here
}.to not_change(user, :avatar_url).from(sample_avatar_url).and not_change(user, :old_avatar).from(nil)
Upvotes: 44