Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 errors 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)"]
like image 533
BvuRVKyUVlViVIc7 Avatar asked Jul 03 '11 16:07

BvuRVKyUVlViVIc7


3 Answers

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.

like image 193
Rameshwar Vyevhare Avatar answered Nov 16 '22 18:11

Rameshwar Vyevhare


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.

like image 3
jake Avatar answered Nov 16 '22 17:11

jake


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.

like image 2
hindenbug Avatar answered Nov 16 '22 19:11

hindenbug