Rails 3 + Rspec 2: Validation failed: Email has already been taken
I have 2 models, User
and Bucket
. User
has_many
Buckets
and a Bucket
belongs_to
a User
.
In factories.rb
, I have:
Factory.define :user do |user|
user.email "teste@test.com"
user.password "foobar"
user.password_confirmation "foobar"
end
Factory.sequence :email do |n|
"person-#{n}@example.com"
end
Factory.define :bucket do |bucket|
bucket.email "user@example.com"
bucket.confirmation false
bucket.association :user
end
and I have a login_user module as follows:
def login_user
before(:each) do
开发者_运维知识库 @request.env["devise.mapping"] = Devise.mappings[:user]
@user = Factory.create(:user)
#@user.confirm!
sign_in @user
end
end
I am using Spork and Watch and my Buckets_controller_spec.rb
is as simple as:
describe "User authenticated: " do
login_user
@bucket = Factory(:bucket)
it "should get index" do
get 'index'
response.should be_success
end
...
end
The error is always the same:
Failures:
1) BucketsController User authenticated: should get index
Failure/Error: Unable to find matching line from backtrace
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
# ./lib/controller_macros.rb:12:in `block in login_user'
And it only happens when I have the Factory(:bucket)
. The login works fine when I don't add the Factory(:bucket)
.
It's always the same error. I have tried adding :email => Factory.next(:email)
to the user, but no success.
Edit:
In rails c test
:
ruby-1.9.2-p180 :019 > bucket = Factory(:bucket, :email => "hello@hello.com")
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
ruby-1.9.2-p180 :018 > Bucket.create(:email => "hello@hello.com")
=> #<Bucket id: 2, email: "hello@hello.com", confirmation: nil, created_at: "2011-04-08 21:59:12", updated_at: "2011-04-08 21:59:12", user_id: nil>
Edit 2:
I found out that the error is in the association, however, I don't know how to fix it.
bucket.association :user
When you define a factory with an association you need to give the factory an object to associate with whenever you use the factory.
This should work:
describe "User authenticated: " do
login_user
@bucket = Factory(:bucket, :user => @user)
it "should get index" do
get 'index'
response.should be_success
end
end
That way factorygirl knows to make a bucket which is associated with @user.
Try this in your user factory:
Factory.define :user do |f|
f.sequence(:email) { |n| "test#{n}@example.com" }
...
end
I think that's probably your problem. When you use f.email = "anyvalue"
it's going to use that value every time. I see you were trying to create a sequence in the next block, but I'm not sure that sequence is getting used.
ALSO - be aware that if you get tests interrupted by a crash or something, sometimes bogus test data can get left in your test DB instead of being rolled back.
Very first thing I try if something worked once and then quit working is to reset the test db.
rake db:test:prepare
That will clean everything out.
If this doesn't work let me know and I'll take a second look!
If someone is getting this recently with your views. Try using Database Cleaner.
For more info: RailsTutorial - chapter 8.4.3 - Test database not clearing after adding user in integration test
精彩评论