Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryGirl and Rspec

I've very green to this TDD business, so any help would be fantastic!

So, I've got a factory with the following:

FactoryGirl.define do

  factory :account do
    email "[email protected]"
    url "teststore"
  end  

end

And an Rspec test with:

  it "fails validation without unique email" do
    account1 = FactoryGirl.create(:account)
    account2 = FactoryGirl.create(:account)
    account2.should have(1).error_on(:email)
end

I get a failure with the following message:

  1) Account fails validation without unique email
     Failure/Error: account2 = FactoryGirl.create(:account)
     ActiveRecord::RecordInvalid:
       Validation failed: Email taken, please choose another, Url taken, please choose another
     # ./spec/models/account_spec.rb:11:in `block (2 levels) in <top (required)>'

Is this the correct way to create new factories? Any ideas what I'm doing wrong here (I have no doubt I'm doing something totally incorrect!)

EDIT: I'm thinking of instead of using 'create' on the second account, I may want to use .build and then .save instead?

like image 612
Galaxy Avatar asked Dec 08 '11 23:12

Galaxy


1 Answers

Save yourself the database interactions and use the build method for situations like this.

it "fails validation without unique email" do
  account1 = create(:account)
  account2 = build(:account)
  account2.should_not be_valid
  account2.should have(1).error_on(:email) 
end

You don't need to try and create an account for valid? to return false. You have access to the errors object on the account even when it's just built in memory. This will decrease database interactions and thus making your tests much faster.

Have you considered using sequences in your factories? I don't know how far along you are with your RSpec / FactoryGirl experience, but you will find that things like the following are very useful.

factories.rb

factory :account do
  sequence(:email) { |n| "user#{n}@example.com" }
  url "teststore"
end

Every time you call build or create on the account factory, you will get unique emails.

Remember that you can always specify values for the attributes on the factory using the options hash. So when testing your uniqueness validation on the account, you would do something like this.

it "fails validation without unique email" do
  account1 = create(:account, :email => "[email protected]")
  account2 = build(:account, :email => "[email protected]")
  account2.should_not be_valid
  account2.should have(1).error_on(:email) 
end
like image 70
Feech Avatar answered Nov 01 '22 16:11

Feech