Проблема валидации с Autotest и Factory Girl

у меня проблема с автотестом. В моей пользовательской модели имя пользователя и адрес электронной почты уникальны. Когда я запускаю автотест, все работает нормально. Во втором туре из автотеста у меня

Ошибка проверки: электронная почта уже занята, имя пользователя уже занято

ошибка только в двух тестах. Я не понимаю, почему, я использую factorygirl с последовательностью, и это должно генерировать каждый раз новое имя пользователя.

Это мой файл rspec2:

describe User do

  specify {  Factory.build(:user).should be_valid }

  context "unique values" do

    before :all do
       @user = Factory.create(:user)
    end


    it "should have an unique email address" do
       Factory.build(:user, :email  => @user.email).should_not be_valid
    end

    it "should have an unique username" do
       Factory.build(:user, :username  => @user.username).should_not be_valid
    end

  end


  context "required attributes" do

    it "should be invalid without an email address" do
       Factory.build(:user, :email => nil).should_not be_valid
    end

    it "should be invalid without an username" do
       Factory.build(:user, :username  => nil).should_not be_valid
    end

    it "should be invalid without an password" do
       Factory.build(:user, :password  => nil).should_not be_valid
    end

    it "should be invalid without an address" do
        Factory.build(:user, :address  => nil).should_not be_valid
    end


  end
end

Фабрика:

Factory.sequence :username do |n|
  "Outfit#{n}er"
end

Factory.sequence :email do |n|
  "user#{n}@example.com"
end

Factory.define :user do |u|
  u.username              { Factory.next :username }
  u.email                 { Factory.next :email }
  u.password              'secret'
  u.phone_number          '02214565854'
  u.association :address, :factory => :address
end

Factory.define :confirmed_user, :parent => :user do |u|
  u.after_build { |user| user.confirm! }
end

Единственные два теста, которые не работают, находятся в контексте «уникальных значений». Все остальные тесты работают без ошибок.

Спасибо


person ThreeFingerMark    schedule 04.01.2011    source источник


Ответы (4)


Это именно та проблема, с которой я только что столкнулся - и у меня был странный опыт, когда эта проблема, казалось, не возникала, если я просто запускал "спекцию рейка".

Не найдя очевидного ответа, я попробовал что-то, что, похоже, решило проблему! Кажется, что установка переменной класса внутри блока before() является виновником, если вы используете FactoryGirl.

У меня было что-то очень похожее:

factory :widget do
  sequence(:name) { |n| "widget#{n}" }
end

тогда:

describe Widget do
  before(:each) { @widget = FactoryGirl.create(:widget) }
  it ...yadda yadda...
    @widget.foo()
  end
end

автотест найдет проблемы с ограничением уникальности. Я изменил тест на уважение к этому:

describe Widget do
  let(:widget) { FactoryGirl.create(:widget) }
  it ...yadda yadda...
    widget.foo()
  end
end

... и проблемы с ограничением уникальности исчезли. Не знаю, почему это происходит, и кажется, что этого не должно происходить, но это может быть рабочим решением.

person dotdotdotPaul    schedule 25.08.2011

У меня возникла эта проблема из-за того, что база данных не очищалась должным образом после некоторых тестов.

Если вы запустите: rake db:test:prepare перед автотестом, произойдет ли это?

В конце концов я обошел это, изолировав, какие тесты не очищались, и исправив их (или удалив). Извините, я не могу вспомнить, в чем была проблема, но это было вызвано какой-то ошибкой.

О, и я запустил его без spork, так что я мог видеть, что мои сообщения регистратора смешиваются с результатами.

Надеюсь это поможет.

person Taylored Web Sites    schedule 16.11.2011

Проблема, вероятно, в вашем файле конфигурации. У вас есть строка в файле конфигурации вашей спецификации (вероятно, spec_helper.rb), которая гласит:

config.use_transactional_fixtures = false

Это должно быть:

config.use_transactional_fixtures = true

Или, если вы не хотите использовать транзакционные фикстуры, у вас должна быть функция before(:each) в вашем тесте:

before :each do
  User.destroy_all
end

В качестве альтернативы я использую гем Sham для своих фабрик, потому что он более совместим с нетранзакционными фикстурами и последовательностями.

person Pan Thomakos    schedule 04.01.2011
comment
Спасибо за ваш ответ. Но у меня есть config.use_transactional_fixtures = true в моем spec_helper.rb - person ThreeFingerMark; 05.01.2011

Я столкнулся с очень похожей проблемой, и я безуспешно попробовал несколько предложений в этой теме. Однако я исправил это, добавив следующее в свой spec_helper.rb:

# Clean up the database
  require 'database_cleaner'
   config.before(:suite) do
     DatabaseCleaner.strategy = :truncation
     DatabaseCleaner.orm = "mongoid"
  end

  config.before(:each) do
    DatabaseCleaner.clean
  end

Также не забудьте добавить гем DatabaseCleaner в ваш гемфайл.

person niharvey    schedule 20.12.2012