Rspec, shoulda, validate_uniqueness_of with scope and wrong error message
I have following Rspec test:
describe Productlimit do
before(:each) do
@productlimit = Factory.create(:productlimit, :user => Factory.create(:user))
end
subject { @productlimit }
...
it { should validate_uniqueness_of(:price_cents).scoped_to(:direction_down, :currency, :market_id, :user_id) }
...
end
But I get following confusing error:
1) Productlimit
Failure/Error: it { should validate_uniqueness_of(:price_cents).scoped_to(:direction_down, :currency, :market_id, :user_id) }
Expected errors to include "has already been taken" when price_cents is set to 9530, got errors: ["direction_down has already been taken (false)"]
Can you help me? I don't understand why this isn't working, because the error message seems to be correct?
EDIT:
This happens too in other situations as well:
# product_spec.rb
...
it { should validate_numericality_of(:price).with_message("price_cents must be greater than 0 (0)") }
# rake spec:models
Failure/Error: it { should validate_numericality_of(:price).with_message("price_cents must be greater than 0 (0)") }
Expected e开发者_StackOverflow中文版rrors to include "price_cents must be greater than 0 (0)" when price is set to "abcd", got errors: ["price_cents must be greater than 0 (0)"]
To check validate_uniqueness_of(:field) but for this you should at lease one record in database to check uniquness constrain. Here is....
before do
@country = FactoryGirl.create(:country, :id =>"a0000007-0000-0000-0000-000000000009",:currency_id => "a0000006-0000-0000-0000-000000000004",:merchant_id => "a0000001-0000-0000-0000-000000000002",:country_code => 'CAN', :name => 'Canada')
end
To validate uniqueness
it { should validate_uniqueness_of(:country_code)}
It will work out try it out.
To add to what Riche has said about uniqueness validation on :direction_down, I would suspect the way your ProductLimit factory generates values for :direction_down. It might not always be generating unique values for all attributes which have the uniqueness validation on them.
Also, one issue I have faced with uniqueness validation is the first object ( the subject in your case) thats is created before the validation check should not have any conflicting values with ones the factory "randomly" generates. To illustrate with a trivial example,
Factory(:product_limit, :direction_down => "abc")
it { should validate_uniqueness_of(:price_cents).scoped_to(:direction_down) }
has the potential to fail wrongly, in case the object constructed by the shoulda matcher ends with direction_down set to "abc" when there is a uniqueness validation on :direction_down.
Do you have the database_cleaner settings in the sepc_helper? if not then add
gem "database_cleaner"
in spec_helper.rb add the following in the RSpec.configure block
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
Also can you post the Factory code? just to have a clearer picture.
I hope this helps.
Also check if there is any uniqueness validation on :direction_down attribute.
Try to remove test/fixtures/*
and try to manually create object before testing uniqueness (not using Factory). Also, have you tried:
class MyModelTest < ActiveSupport::TestCase
The error isn't correct for the matcher because it's complaining about the uniqueness of :direction_down when you asked it to test that the uniqueness of :price_cents was valid.
Does the code for your model include a validates_uniqueness_of :direction_down
? If so, that would explain the message.
The first case (with validate_uniquess_of
) happened to me after an unexpected crash. A simple rake db:test:prepare
fixed it.
精彩评论