Как избежать Постоянства объекта Factory Girl - PullRequest
3 голосов
/ 21 июля 2011

У меня есть несколько тестов rspec, которые используют Factory_girl. Он используется в MongoDB с MongoId в приложении Rails 3.

Где-то вдоль линии я проверяю на недопустимые значения: ожидание ошибок валидации. После этого, каждый раз, когда я звоню Factory(:user), происходит сбой из-за ошибок проверки. Я ожидал бы совершенно новый и чистый объект, когда я вызываю Factory (: user), а не повторно используемый, побитый.

Пример кода ниже, иллюстрирует * user_spec.rb * добавление недопустимых элементов в «роли». Пользовательская модель успешно помечает запись как неверная .

Чуть дальше в спецификациях, * sidebar_helper_spec.rb * необходимо создать экземпляр @user, и там он не работает, сообщая мне, что недопустимая роль "foo" существует. Но вы можете ясно видеть, что эта роль отсутствует в factory.rb .

Это ожидаемое поведение? Можно ли переключить постоянство (или кэширование?) С помощью параметра конфигурации?

## 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       ['jobseeker']
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

1 Ответ

1 голос
/ 26 мая 2013

= создает новый массив ["banned", "jobseeker"] и устанавливает его на @user.roles:

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

НО << добавляется "foo"к уже существующему массиву (то есть изменяет существующий массив!):

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

FactoryGirl - это не , повторно использующий тот же объект пользователя, но повторно использующий тот же атрибут roles.Просто измените массив roles, чтобы он создавался динамически каждый раз на фабрике:

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

Либо это, ИЛИ избегайте использования << или любого метода, который изменяет существующий массив /переменная, и вместо этого используйте =, который использует новый объект.например,

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