'AssociationTypeMismatch and FactoryGirl
This has been causing some frustration recently...
It seems that using Factories in my cucumber tests, in some situations causes AssociationTypeMismatch
errors such as:
MyModel(#65776650) expected, got MyModel(#28190030) (ActiveRecord::AssociationTypeMismatch)
These seem to happen when there is an association reference - as if the Factory created object is different to the real one. See this question for more details: Cucumber duplicate class problem: AssociationTypeMismatch
I have been gradually changing Factory calls to real Model.create or mock_model calls. It would be nice to keep using Factory girl... I wonder if there is something I may have done wrong?
Thank you
Solution 1:[1]
I had this happening with me on Rails 3.1.0 rc5, and got it working.
To expand on Jonas' answer.
You should change your Gemfile to be like this:
gem 'factory_girl', '~> 2.0.0', :require => false
gem 'factory_girl_rails', '~> 1.1.0', :require => false
And then if you are using Spork, make your spec/spec_helper.rb file look like this:
Spork.each_run do
require 'factory_girl'
require 'factory_girl_rails'
end
Solution 2:[2]
It seems to happen if ActiveSupport unloads and reloads a constant that you have a reference to. I've experienced the same with Rspec/Capybara, and what helped was a mixture of different things:
- Make sure you have cached_classes set to false in your test environment (config/environments/test.rb)
- In your gemspec, try replacing require 'factory_girl_rails' with 'factory_girl'
I'm using Spork (a test server), which seems to make this stuff increasingly difficult. If you are using a test server, evaluate whether you should put ', :require => false' after factory_girl in your gemspec.
The topic is also covered in this google groups thread
Please let us know if any of this helped.
Solution 3:[3]
If you're using Spork, make sure to reload your factories after reloading your models.
E.g.
Spork.each_run
if Spork.using_spork?
print "Reloading models ... "
ActiveSupport::Dependencies.clear
puts "done"
print "Reloading factories ... "
FactoryGirl.reload
puts "done"
end
end
Solution 4:[4]
This happens because cache_classes is false, as is required by Spork. Capybara reloads Rails classes for every request (or, to be correct, Rails' reloader middleware does, which is not called for normal tests), and this freaks out the factories (exactly why, I'm not sure). You can either reload them, or simply run your Capybara specs outside of Spork.
So you need two things: to only run Capybara outside of Spork, and to set cache_classes to false only for Spork.
To only run Capybara outside of Spork, I have a Guardfile that runs specs in spec/requests outside of Spork and other specs inside of Spork here:
https://gist.github.com/1731900
Then, in config/environments/test.rb
:
config.cache_classes = !ENV['DRB']
Your Capybara specs will be a bit slower, as they need to boot rails, but everything will Just Work.
Solution 5:[5]
I had some success with reloading the Factory definitions try something like this:
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
Solution 6:[6]
I ran into this issue when I passed the "class" option to my factory that was inherited by other factories:
factory :draft_resource, :class => Resource do
factory :resource, :parent => :draft_resource do
The only solution I could find was to simply not do this.
Solution 7:[7]
I ran into this same issue and spent probably ten hours trying every solution on this thread and everywhere else on the web. I started ripping out huge chunks of code trying to get it as close to another app of mine in which I couldn't reproduce the problem. Finally, I came across some helper functions in my spec_helper file:
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
helper intended to work both in controller and request specs. And it does, sort of--just not with spork. When I removed the capybara helpers the issue was resolved:
def sign_in(user)
cookies[:remember_token] = user.remember_token
end
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | staackuser2 |
Solution 2 | Community |
Solution 3 | duma |
Solution 4 | bhuga |
Solution 5 | Lars Klevan |
Solution 6 | gabeodess |
Solution 7 | lobati |