In RSpec, when you first start writing test cases to compare expected results, it might be very confusing to pick from "be", "eq", "eql" or "equal".
However, once you know the underlying differences of these methods, everything will be clear afterward. Let me go through them here with some examples.
Compare Statements
There are 2 groups of compare methods.
The followings compare the value of the object:
- eq
- eql
These two compare the object_id of the object instead:
- equal
- be
Test Case Example
In the following test case, I am going to use String, Array and Fixnum data to demonstrate the differences of "eq", "eql", "equal", "be".
Fixnum
require 'rails_helper'
describe 'Fixnum' do
it('should find two Fixnums are equal') { 1.should eq 1 }
it('should find two Fixnums are equal') { 1.should eql 1 }
it('should find two Fixnums are equal') { 1.should equal 1 }
it('should find two Fixnums are equal') { 1.should be 1 }
end
In case of Fixnum, it will all process successful. It is because Fixnum with the same value are actually the same single data instance, i.e. 1 and 1 are referring the same instance in the memory.
String
describe 'String' do
it('should find two strings are equal') { "".should eq ""}
it('should find two strings are equal') { "".should eql ""}
it('should find two Strings are equal') { "".should equal ""} # Failed
it('should find two strings are equal') { "".should be ""} # Failed
end
In case of String, it will fail on "equal" and "be" statements. It is because these String data are different instances. First two test cases are comparing their values, which are the same. However, third and fourth test cases are comparing if they are the same object instance, which is not.
Array
describe 'Array' do
it('should find two Arrays are equal') { {:a => 1}.should eq :a => 1 }
it('should find two Arrays are equal') { {:a => 1}.should eql :a => 1 }
it('should find two Arrays are equal') { {:a => 1}.should equal :a => 1 } # Failed
it('hould find two Arrays are equal') { {:a => 1}.should be :a => 1 } # Failed
end
In case of Array, it will fail on "equal" and "be" statements. The reason are the same as String cases.
Conclusion
We can see that "eq" and "eql" are used to compare the object value,
while "equal" and "be" are used to compare the object_id by referencing the above result.
That's mean the compare statements of checking the object_id are using for compare the Fixnum data.
The compare statements of checking the object value are using for compare the normal data type, e.g. String, Array ...
Reference
Suzuki MilanPaak. 17 JUN 2012. RSpecのequal, eql, eq, be の違い. Retrieved from :
http://engineerflies.blogspot.hk/2012/06/rspecequal-eql-eq-be.html#.WWght9OGOi5
myronmarston. Last published at May 2017. Equality matchers. Retrieved from :
https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/equality-matchers