RSpec has two equality matchers: eq
and be
. Depending on the circumstances, eq
works most of the time. The difference between the two is subtle. The result of understanding the difference will yield clearer and more reliable specs.
Take this contrived example which expects a user name to be "Jon".
RSpec.describe User, "#name", type: :model do
let(:user) { Fabricate(:user, name: "Jon") }
scenario "User's name is Jon" do
expect(user.name).to be("Jon")
end
end
Running this test we get a failure.
Failures:
1) User's name is Jon
Failure/Error: expect(user.name).to be "Jon"
expected #<String:70298288643660> => "Jon"
got #<String:70298288643700> => "Jon"
...
...
It's failing and rightfully so! RSpec's be
matcher expects both entities to be the same object. In other words, user.name
and the string "Jon"
are expected to have the same object_id.
irb
irb(main):001:0> jon = "Jon"
=> "Jon"
irb(main):002:0> "Jon"
=> "Jon"
irb(main):003:0> jon == "Jon"
=> true
irb(main):004:0> jon.equal?("Jon")
=> false
irb(main):005:0> jon.object_id
=> 70185646150880
irb(main):005:0> "Jon".object_id
=> 70185646097920
Notice the object ids are different. Under the hood, RSpec is calling Object#equal?
which is a check at the object level.
RSpec's eq
, is what you expect the string value to be matched against. Going back to our earlier example:
RSpec.describe User, "#name", type: :model do
let(:user) { Fabricate(:user, name: "Jon") }
scenario "User's name is Jon" do
expect(user.name).to eq("Jon")
end
end
After you run your spec, you're passing!
Finished in 1.12 seconds (files took 13.85 seconds to load)
1 example, 0 failures
Randomized with seed 4227
...
...
The user's name value is "jon". That's the same as the value of the string "Jon". Peaking under the hood again.. RSpec eq
invokes ===
on the two objects which checks the return value.
TLDR
eq
checks if the object values are the same
be
checks if the objects are the same
Top comments (1)
Great to know this.. I always try to use
be()
for object checks.eq()
for values andeql()
values of the same type.