AssociationTypeMismatch и FactoryGirl
Это вызвало некоторое разочарование в последнее время...
Кажется, что использование фабрик в моих тестах огурца в некоторых ситуациях вызывает ошибки AssociationTypeMismatch, такие как:
MyModel (# 65776650) ожидается, получил MyModel (# 28190030) (ActiveRecord:: AssociationTypeMismatch)
Кажется, что это происходит, когда есть ссылка на ассоциацию - как будто созданный объект Factory отличается от реального. См. Этот вопрос для получения дополнительной информации: Задача класса дубликатов огурца: AssociationTypeMismatch
Я постепенно меняю призывы Factory к реальным вызовам Model.create или mock_model. Было бы неплохо продолжать использовать Factory девушку... Интересно, есть ли что-то, что я, возможно, сделал не так?
Спасибо
Ответы
Ответ 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