15

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)"]
lucapette
  • 20,564
  • 6
  • 65
  • 59
BvuRVKyUVlViVIc7
  • 11,641
  • 9
  • 59
  • 111
  • what versions of shoulda/rspec are you using? – nathanvda Jul 11 '11 at 10:58
  • I have shoulda-matchers (1.0.0.beta2), but i tried it with the current 'shoulda' gem as well.. – BvuRVKyUVlViVIc7 Jul 11 '11 at 15:08
  • it seems to me that you are testing something that rails should already be testing. if you have validate_numericality of in your model, why also call it in your tests? that's unnecessary duplication – corroded Jul 12 '11 at 10:00
  • 6
    if the validation is part of the specification of the behavior, he should be testing it. – Keith Gaddis Jul 12 '11 at 17:37
  • Does the Factory.create call succeed by itself? You might try isolating this test by running it on a Productlist.new(:price_cents => ...) object. – Thilo Jul 16 '11 at 20:47
  • The factory creation works quite well, no errors or warnings... – BvuRVKyUVlViVIc7 Jul 17 '11 at 01:45
  • Do you mind adding the Productlimit model code as well, in the question? – karthiks Jul 21 '11 at 17:08
  • Two things I'd like to point out: (1) Factory.create hits the database, use .build instead so it just creates the object without the record. You can still check validations on non-stored records. (2) Move the factory to a let, so that it's lazy evaluated in the scope of the description/context block. – krainboltgreene Nov 26 '11 at 04:57

6 Answers6

12

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.

Rameshwar Vyevhare
  • 2,699
  • 2
  • 28
  • 34
3

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.

Community
  • 1
  • 1
jake
  • 2,371
  • 1
  • 20
  • 31
2

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.

hindenbug
  • 549
  • 1
  • 8
  • 15
  • Thanks for your answer, ich removed now this specific test and test it myself manually... Tried your solution, but didnt work either.. – BvuRVKyUVlViVIc7 Jul 23 '11 at 18:22
0

The first case (with validate_uniquess_of) happened to me after an unexpected crash. A simple rake db:test:prepare fixed it.

Nicolas Buduroi
  • 3,565
  • 1
  • 28
  • 29
0

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 
0

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.

Ritchie
  • 1,486
  • 1
  • 15
  • 19