AssociationTypeMismatch и FactoryGirl - PullRequest
       4

AssociationTypeMismatch и FactoryGirl

18 голосов
/ 28 февраля 2011

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

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

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

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

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

Спасибо

Ответы [ 7 ]

8 голосов
/ 15 августа 2011

У меня это происходило со мной на 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
4 голосов
/ 22 января 2013

Если вы используете 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 голосов
/ 30 апреля 2011

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

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

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

Эта тема также рассматривается в этой ветке групп Google

Пожалуйста, дайте нам знать, если это помогло.

2 голосов
/ 03 февраля 2012

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

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

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

https://gist.github.com/1731900

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

config.cache_classes = !ENV['DRB']

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

1 голос
/ 30 апреля 2013

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

factory :draft_resource, :class => Resource do

factory :resource, :parent => :draft_resource do

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

1 голос
/ 08 июня 2011

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

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
0 голосов
/ 04 апреля 2013

Я столкнулся с той же проблемой и провел, вероятно, десять часов, пытаясь найти решение в этой теме и везде в Интернете.Я начал вырывать огромные куски кода, пытаясь приблизить его к другому моему приложению, в котором я не мог воспроизвести проблему.Наконец, я обнаружил некоторые вспомогательные функции в моем файле 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 помощник, предназначенный для работы как в спецификации контроллера, так и в спецификации запроса.И это как бы - только не со спорком.Когда я удалил помощников капибары, проблема была решена:

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