RSPEC and factory girl SystemStackError: stack level too deep

Aurelien Schlumberger picture Aurelien Schlumberger · Nov 27, 2011 · Viewed 7.6k times · Source

I have trying to solve an issue with my Spec tests and I get the following error Failures:

  1) SessionsController POST 'create' with valid email and password should sign in the user
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/Aurelien/.rvm/gems/ruby-1.9.2-p290@rails3/gems/activerecord-3.1.0/lib/active_record/connection_adapters/abstract/connection_specification.rb:103

Finished in 37.77 seconds
9 examples, 1 failure

Failed examples:

rspec ./spec/controllers/sessions_controller_spec.rb:35 # SessionsController POST 'create' with valid email and password should sign in the user

Prior to this I had problems with associations with my factories.

Factory.define :role do |role|
  role.name                   "Registered"
  role.association :user, :factory => :user
end

Factory.define :admin do |role|
  role.name                   "Admin"
  role.association :user, :factory => :user
end

Factory.define :user do |user|
  user.first_name             "Foo"
  user.last_name              "Bar"
  user.email                  "[email protected]"
  user.password               "foobar"
  user.password_confirmation  "foobar"
  user.status                 "At foobar"
  user.description            "Lorem Ipsum sit dolor amet."
  user.username               "foobar"
  user.association :role, :factory => :role
  user.association :admin, :factory => :role
end

Factory.define :user_with_admin_role, :parent => :user do |user|
  user.after_create { |u| Factory(:role, :user => u) }
end

Factory.define :reg_user do |user|
  user.first_name             "bar"
  user.last_name              "foo"
  user.email                  "[email protected]"
  user.password               "foobar"
  user.password_confirmation  "foobar"
  user.status                 "At foobar"
  user.description            "Lorem Ipsum sit dolor amet."
  user.username               "barfoo"
  user.association :role, :factory => :role
end

and my session tests so far are:

describe "POST 'create'" do
    describe "invalid signin" do
      before(:each) do
        @attr = { :email => "[email protected]", :password => "invalid" }
      end

      it "should re-render the 'new' page with a flash error" do
        post :create, :session => @attr
        flash.now[:error] =~ /invalid/i
        response.should render_template('new')
      end

    end

    describe "with valid email and password" do

      before(:each) do
        @user = Factory(:user)
        @attr = { :email => @user.email, :password => @user.password}
      end

      it "should sign in the user" do
        post :create, :session => @attr
        controller.current_user.should == @user
      end

    end

  end

I am really not sure what is creating the problem. In my model I assign a default role to every user as "Registered" and the "Admin" role for the first user.

user.rb

def assign_default_role
    if User.count == 0
      self.roles << Role.find_by_name("Admin")
      self.roles << Role.find_by_name("Registered")
    end
    self.roles << Role.find_by_name("Registered") unless User.count == 0
  end

Any advise would be most welcome. Thanks

Answer

Dylan Markow picture Dylan Markow · Nov 27, 2011

The problem line is this:

@user = Factory(:user)

You have a circular reference: your :user factory creates a :role and :admin factory. Then the :role and :admin factories each create another :user factory, which then creates yet another :role and :admin factory, and so on until you get a stack level too deep error.

You'll need to remove the associations from some of these. I'd recommend removing the role.association lines from both :role and :admin. Whenever you create a :user, it will still create the :role and :admin lines for you.