everydayrails / rspec_rails_4

Everyday Rails Testing with RSpec (Rails 4.0 Edition)
MIT License
270 stars 144 forks source link

build does not seem to be raising expected uniqueness error #104

Open mgudapak opened 10 years ago

mgudapak commented 10 years ago

Disclaimer: I am new to RSpec and trying to build tests on an existing app using the some of the examples in this book. The below is replicating a test similar to the one on page 35 of your PDF.

I have a 'Price' Model which has only one required column 'id' which is unique and set to AUTO_INCREMENT at the database (MySQL) level.

My factory is setup as below

# spec/factories/prices.rb

FactoryGirl.define do
  factory :price do
  end
end

My spec is as follows

# spec/models/price_spec.rb
require 'spec_helper'

describe Price do
  it "has a valid factory" do
    expect(create(:price)).to be_valid # this passes
  end

  it "is invalid when id is duplicate" do
    create(:price, id: 29595276)
    expect(build(:price, id: 29595276)).to have(1).errors_on(:id) # this fails
  end
end

The RSpec error I get is as follows

Price
  has a valid factory
  is invalid when id is duplicate (FAILED - 1)

Failures:

  1) Price is invalid when id is duplicate
     Failure/Error: expect(build(:price, id: 29595276)).to have(1).errors_on(:id) # this passes
       expected 1 errors on :id, got 0
     # ./spec/models/price_spec.rb:13:in `block (2 levels) in <top (required)>'

Finished in 0.1942 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/models/price_spec.rb:11 # Price is invalid when id is duplicate

Am I doing something wrong or testing something that I shouldn't be testing with RSpec (since the database will take care of enforcing uniqueness)? I was expecting that the 'DuplicateRecord' error from MySQL would be captured and reported as an error resulting in my test passing - right?

Any pointers would be very helpful. Cheers

diegosouza commented 10 years ago

Hello @mgudapak,

Testing a factory doesn't make sense. It's only to help you to create proper objects easier. Also trying to test uniqueness this way doesn't make any sense. Probably you'll want to use the shoulda matcher like this:

it { should validate_uniqueness_of(:entity_attribute) }