New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Composed change
matcher does not always detect internal mutations
#1131
Comments
👋 This has nothing to do with the composition, the hashes are just equal before / after mutation of the attributes, so we need to improve the detection of changes here. |
Another way to fix this is to implement class SomethingExpected
attr_accessor :some_value
def hash
some_value.hash
end
end It's a temporary solution. It may also be problematic if you happen to use those objects as Hash keys (will have to Agree that even though that if the hash has not changed is not an 100% indication that the object itself didn't change, since the set of allowed values of a hash is limited. |
The solution I've been working up involves using the instance attributes of an object as an additional hash signature, see #1132 |
Closed by #1132 |
Hi @JonRowe, We should reopen this issue as #1132 has been reverted, and as of rspec 3.10.0, this is still an annoying and unexpected issue. Annoying an unexpected considering the given message that makes us think that that should work and the issue is in our code:
For lurkers, a possible workaround being turning: expect {
# things
}.to change { model }
.from(having_attributes(foo: "a"))
.to(having_attributes(foo: "b")) into: expect {
# things
}.to change(model, :attributes)
.from(a_hash_including("foo" => "a"))
.to(a_hash_including("foo" => "b")) Thanks! |
Tracked in rspec/rspec-rails#1173 |
Yeah I think this is better off as a rspec-rails concern, it could extend the base change matcher to detect models and check attributes instead, but the main rspec gems don't know about rails |
As mentioned in rspec/rspec-rails#1173 another workaround is to call expect {
# things
}.to change { model.dup }
.from(having_attributes(foo: "a"))
.to(having_attributes(foo: "b")) |
Subject of the issue
When invoking the
change
matcher composed with another matcher (herehave_attributes
), actions that change neither subject equality nor#hash
do not result in detection of a change at all. This is not necessarily true of the matcher with which it is composed.Your environment
Steps to reproduce
Expected behavior
Both of these tests should pass.
Actual behavior
The test with direct use of
have_attributes
passes; the test usingchange
fails.Notes
I recognise that
#==
not respecting these attributes is potentially problematic. It seems worth noting that I encountered this in a Rails app, given #1100.There seem to be some semantic difficulties with
change
and composition. This might suggest documenting this restriction over breaking it. I'd be happy to take a stab at implementing either of these (if documenting, I'd like to see a matcher that does allow for this sort of approach)The text was updated successfully, but these errors were encountered: