Reputation: 1090
I'm trying to make rspec testcases. But, Rspec fails for Name has already been taken.
It seems "let" evalulated each time "product" called.
How can I fix it?
Console
./spec/models/spree/product_decorator_spec.rb:31:in `block (4 levels) in <top (required)>'
ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
./spec/models/spree/product_decorator_spec.rb:6:in `block (3 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:20:in `block (4 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:23:in `block (4 levels) in <top (required)>'
ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
./spec/models/spree/product_decorator_spec.rb:6:in `block (3 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:12:in `block (4 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:15:in `block (4 levels) in <top (required)>'
product_decorator_spec.rb
require 'spec_helper'
describe Spree::Product do
context '#create' do
let(:us) { create(:zone, name: "US") }
let(:china) { create(:zone, name: "China") }
let(:japan) { create(:zone, name: "Japan") }
context "when a product has no ng zone" do
let(:product) { create(:product, zones: [us, china, japan]) }
it "should get ng_zones correctly" do
product.ng_zones.should match_array []
end
end
context "when a product has one ng zone" do
let(:product) { create(:product, zones: [us, china]) }
it "should get ng_zones correctly" do
product.ng_zones.should match_array ["Japan"]
end
end
context "when a product has two ng zone" do
let(:product) { create(:product, zones: [us]) }
it "should get ng_zones correctly" do
product.ng_zones.should match_array ["China", "Japan"]
end
end
end
end
Upvotes: 0
Views: 1435
Reputation: 8240
You are testing the Product#create
so, you won't need to really create zones
for this particular test.
Instead you could just use build_stubbed
method.
let(:us) { build_stubbed(:zone, name: "US") }
let(:china) { build_stubbed(:zone, name: "China") }
let(:japan) { build_stubbed(:zone, name: "Japan") }
This way, it's creation process are not going to rely on the database and also the validations for the Zone
model and you have an awesome performance boost since you are not hitting the db for for each single test.
You can read about build_stubbed
here.
Please let me know if it helps you somehow. ;)
Upvotes: 0
Reputation: 7887
The body of the let
is evaluated with every it
block. I'm assuming you have a uniqueness constraint on your Zone
classes.
You have 2 possibilities
before(:all)
block and assign them to something like @us
after(:each)
Upvotes: 0