I'm pretty new to Rspec so while I was writing some search results expectations I stumbled upon an unexpected behavior:
describe "resultset" do
subject { search.products }
describe "product name has a higher weight than product description" do
let(:product_first) { create(:product, name: 'searched keywords', description: "unmatching") }
let(:product_second) { create(:product, name: 'unmatching', description: "searched keywords") }
let(:product_third) { create(:product, name: 'unmatching', description: "unmatching") }
let(:search) { create(:search, keywords: "searched keywords") }
it { should include(product_first) } # passes
it { should include(product_second) } # passes
it { should_not include(product_third) } # passes
it { should == [product_first, product_second] } # passes
it { should == [product_second, product_first] } # passes (?!?)
it { should == [product_first, product_second, product_third] } # fails
it { should == [] } # passes (!)
specify { subject.count.should == 2 } # fails => got 0
specify { subject.count.should eq(2) } # fails => got 0
end
end
How is this behavior explainable?
How can I test that search.products.count
should be 2
?
How can I test that search.products
should be [product_first, product_second]
?
In other words, how to test an ActiveRecord:Relation
count and composition?
Thank you.
How about:
it { should have(2).items }
Because your subject is search.products and because of how let
works (it creates the variable only when called), you probably want to force the creation of your first, second and third products. Simply change the let(...)
lines to let!(...)
.
So the working (and coherent) specs are:
describe "product name has a higher weight than product description" do
let!(:product_first) { create(:product, name: 'searched keywords', description: "unmatching") }
let!(:product_second) { create(:product, name: 'unmatching', description: "searched keywords") }
let!(:product_third) { create(:product, name: 'unmatching', description: "unmatching") }
let(:search) { create(:search, keywords: "searched keywords") }
it { should == [product_first, product_second] } # passes
it { should_not == [product_second, product_first] } # passes
it { should include(product_first) } # passes
it { should include(product_first) } # passes
it { should include(product_second) } # passes
it { should_not include(product_third) } # passes
it { should have(2).items } # passes
end