开发者

How to avoid Persistence of a Factory Girl object

I have several rspec tests that use Factory_girl. It is used on MongoDB with MongoId in a Rails 3 app.

Somewhere along the line, I test against invalid values: expecting validation-errors. After that, anytime I call Factory(:user), it fails, because of validation errors. I would expect an entirely new and clean object, when I call Factory(:user), not a re-used, battered one.

Example code below, illustrates the *user_spec.rb* adding invalid items to "roles". The user model successfully marks the record as invalid.

A little further in the specs, a *sidebar_helper_spec.rb* need to instantiate an @user, and there it fails, telling me that the invalid role "foo" is there. But you can clearly see that this role is not present in the factory.rb.

Is this expected behaviour? Can I toggle the persistence (or caching?) with a config option?

## models/user_spec.rb

require 'spec_helper'
describe User do
  describe 'roles' do
    before(:each) do
      @user = Factory.build(:user)
    end
    it 'should require a role' do
      @user.roles = nil
      @user.should_not be_valid
    end
    it 'should allow one role from set of defined roles' do
      #@user.roles is preset in factory with "jobseeker"
      @user.should be_valid
    end
    it 'should reject undefined roles' do
      @user.roles << "foo"
      @user.should_not be_valid
    end
    it 'should allow multiple roles' do
      @user.roles = ["banned", "jobseeker"]
      @user.should be_valid
    end
  end
end

## helpers/sidebar_helper_spec.rb

require 'spec_helper'
describe SidebarHelper do
  before(:each) do
    @user = Factory.create(:user) #fails with Mongoid::Errors::Validations: Validation failed - Roles foo is an invalid role.
    @profile = Factory.create(:profile)
  end

  # Has many specs, but all Fail on error in the before(:each)
end

## Actual factory.rb

Factory.define :user do |f|
  f.password    'mischief managed'
  f.email       'h.potter@gryffindor.hogwards.edu.wiz'
  f.roles       ['jobse开发者_运维技巧eker']
end
Factory.define :employer do |f|
  f.password    'butterscotch'
  f.email       'dumbledore@staff.hogwards.edu.wiz'
  f.roles       ['employer']
end

Factory.define :profile do |f|
  f.available true
  f.sync false
end


= creates a new array ["banned", "jobseeker"] and sets it to @user.roles:

# should allow multiple roles
@user.roles = ["banned", "jobseeker"]

BUT << appends "foo" to the already existing array (i.e. modifies the existing array!):

# should reject undefined roles
@user.roles << "foo"

FactoryGirl is not reusing the same user object, but its re-using the same roles attribute. Just change the roles array to be dynamically created each time in the factory:

Factory.define :user do |f|
  ...
  f.roles       { ['jobseeker'] }
end
Factory.define :employer do |f|
  ...
  f.roles       { ['employer'] }
end

Either this, OR avoid using << or any method which changes an existing array/variable, and instead use = which uses a new object. e.g.

# should reject undefined roles
@user.roles = [ "foo" ]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜