26

I am trying to simulate a session using FactoryGirl/shoulda (it worked with fixtures but i am having problems with using factories). I have following factories (user login and email both have unique validations):

Factory.define :user do |u| 
 u.login 'quentin'
 u.email 'quentin@example.com'
end

Factory.define :session_user, :class => Session do |ses| 
 ses.association :user, :factory => :user
 ses.session_id 'session_user'
end

and here's the test

class MessagesControllerTest < ActionController::TestCase

 context "normal user" do
  setup do 
   @request.session[:user_id]=Factory(:user).id
   @request.session[:session_id]=Factory(:session_user).session_id
  end

  should "be able to access new message creation" do
   get :new
   assert_response :success
  end
 end
end

but when i run rake test:functionals, I get this test result

 1) Error: 
  test: normal user should be able to access new message creation. (MessagesControllerTest):
  ActiveRecord::RecordInvalid: Validation failed: Account name already exists!, Email already exists!

which means that record already exists in db when I am referring to it in the test setup. Is there something I don't understand here? does FactoryGirl create all factories in db on startup?

rails 2.3.5/shoulda/FactoryGirl

Mar
  • 7,765
  • 9
  • 48
  • 82
Pavel K.
  • 6,697
  • 8
  • 49
  • 80

1 Answers1

38

Factory(:user) is a shortcut for Factory.create(:user) so within your setup you are creating two objects and saving them to the database.

Factory.build(:user) will create you a user record without saving it to the DB.

EDIT

Within your session_user factory you are creating a user and then creating another within your test setup. FactoryGirl will create a new user record because you have the association in the session_user factory.

You can either get your user instance from the session_user object as follows :-

 context "normal user" do
  setup do
   session = Factory(:session_user)  
   @request.session[:session_id] = session.session_id
   @request.session[:user_id] = session.user_id
  end

or you can add some details to the user factory to ensure unique name and email addresses as follows :-

Factory.define :user do |u| 
 u.sequence(:login) {|n| "quentin#{n}" }
 u.sequence(:email) {|n| "quentin#{n}@example.com"}
end
theUtherSide
  • 3,338
  • 4
  • 36
  • 35
Steve Weet
  • 28,126
  • 11
  • 70
  • 86
  • 1
    but i have only one Factory(:user) mention in my code. why does it run twice? (second is Factory(:session_user), which is a Session instance) – Pavel K. Apr 23 '10 at 09:19