Подтвердить что ты не робот

AssociationTypeMismatch и FactoryGirl

Это вызвало некоторое разочарование в последнее время...

Кажется, что использование фабрик в моих тестах огурца в некоторых ситуациях вызывает ошибки AssociationTypeMismatch, такие как:

MyModel (# 65776650) ожидается, получил MyModel (# 28190030) (ActiveRecord:: AssociationTypeMismatch)

Кажется, что это происходит, когда есть ссылка на ассоциацию - как будто созданный объект Factory отличается от реального. См. Этот вопрос для получения дополнительной информации: Задача класса дубликатов огурца: AssociationTypeMismatch

Я постепенно меняю призывы Factory к реальным вызовам Model.create или mock_model. Было бы неплохо продолжать использовать Factory девушку... Интересно, есть ли что-то, что я, возможно, сделал не так?

Спасибо

4b9b3361

Ответ 1

У меня было это со мной на Rails 3.1.0 rc5, и он работал.

Чтобы расширить ответ Джонаса.

Вы должны изменить свой Gemfile таким образом:

gem 'factory_girl', '~> 2.0.0', :require => false
gem 'factory_girl_rails', '~> 1.1.0', :require => false

И затем, если вы используете Spork, создайте файл spec/spec_helper.rb следующим образом:

Spork.each_run do
 require 'factory_girl'
 require 'factory_girl_rails'
end

Ответ 2

Кажется, что если ActiveSupport выгружает и перезагружает константу, к которой у вас есть ссылка. Я испытал то же самое с Rspec/Capybara, и то, что помогло, было смешением разных вещей:

  • Убедитесь, что в тестовой среде установлено значение cached_classes равным false (config/environment/test.rb)
  • В вашем gemspec, попробуйте заменить require 'factory_girl_rails' на 'factory_girl'

Я использую Spork (тестовый сервер), который, похоже, делает этот материал все более сложным. Если вы используете тестовый сервер, оцените, следует ли вам поставить ",: require = > false" после factory_girl в вашем gemspec.

Тема также рассматривается в этом потоке групп google

Пожалуйста, сообщите нам, помогло ли это.

Ответ 3

Если вы используете Spork, обязательно перезагрузите свои фабрики после перезагрузки своих моделей.

например.

Spork.each_run
  if Spork.using_spork?
    print "Reloading models ... "
    ActiveSupport::Dependencies.clear
    puts "done"

    print "Reloading factories ... "
    FactoryGirl.reload
    puts "done"
  end
end

Ответ 4

Это происходит потому, что cache_classes является ложным, как того требует Spork. Capybara перезагружает классы Rails для каждого запроса (или, если быть верным, промежуточное ПО reloader Rails делает, что не вызывается для нормальных тестов), и это задирает фабрики (именно поэтому я не уверен). Вы можете либо перезагрузить их, либо просто запустить спецификации Capybara за пределами Spork.

Итак, вам нужно две вещи: запустить Capybara вне Spork и установить cache_classes в false только для Spork.

Чтобы запустить Capybara вне Spork, у меня есть Guardfile, который запускает спецификации в spec/request вне Spork и другие спецификации внутри Spork здесь:

https://gist.github.com/1731900

Затем в config/environments/test.rb:

config.cache_classes = !ENV['DRB']

Ваши спецификации Capybara будут немного медленнее, так как они должны загружать рельсы, но все будет работать только.

Ответ 5

У меня был некоторый успех при перезагрузке определений Factory, попробуйте что-то вроде этого:

class Factory
  def self.reload_definitions #:nodoc:
    self.factories.clear
    definition_file_paths.each do |path|
      load("#{path}.rb") if File.exists?("#{path}.rb")

      if File.directory? path
        Dir[File.join(path, '*.rb')].each do |file|
          load file
        end
      end
    end
  end
end

Ответ 6

Я столкнулся с этой проблемой, когда передал параметр класса для моего factory, который был унаследован другими фабриками:

factory :draft_resource, :class => Resource do

factory :resource, :parent => :draft_resource do

Единственное решение, которое я смог найти, это просто не делать этого.

Ответ 7

Я столкнулся с этой же проблемой и потратил, вероятно, десять часов, пытаясь решить все проблемы в этом потоке и всюду в Интернете. Я начал вырывать огромные куски кода, пытаясь найти его как можно ближе к другому приложению, в котором я не мог воспроизвести проблему. Наконец, я столкнулся с некоторыми вспомогательными функциями в файле spec_helper:

def sign_in(user)              
  visit signin_path            
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password 
  click_button "Sign in"       

  # Sign in when not using Capybara as well.
  cookies[:remember_token] = user.remember_token if defined?(cookies)
end

A sign_in помощник, предназначенный для работы как в спецификации контроллера, так и в запросе. И это действительно так, просто не со свистом. Когда я удалил помощников capybara, проблема была решена:

def sign_in(user)              
  cookies[:remember_token] = user.remember_token
end