AssociationTypeMismatch errors

605 views
Skip to first unread message

Travis Pew

unread,
Apr 21, 2011, 1:20:49 PM4/21/11
to factory_girl
I've been struggling to get factory_girl to work with my capybara
acceptance tests, and I *think* the issue is a factory_girl one, not
primarily a capybara one.

In short, if I do a certain number of things (especially use
Factory.create in a before step, and then use again in the second
example), I get AssociationTypeMismatch errors like:

Failure/Error: item = Factory.create(:item, :user =>
Factory.create(:user))
ActiveRecord::AssociationTypeMismatch:
User(#26066800) expected, got User(#29604420)

I have put up an example project on github, and the error occurs for
me on at least two machines:

https://github.com/travisp/Failing-acceptance-test-example

Am I using Factory Girl wrong? From what I can tell, factory_girl
seems to somehow be holding onto the wrong object and ending up with
duplicate classes.

Joe Ferris

unread,
Apr 21, 2011, 1:23:38 PM4/21/11
to factor...@googlegroups.com
That happens if ActiveSupport unloads and reloads a constant that you have a reference to. factory_girl does keep references to build classes, but this isn't generally a problem because tests don't unload constants. Do you have cache_classes set to false for your test environment? Are you using spork or anything else that affects the load order?

--
Individuals over processes. Interactions over tools. Agile Rails training from thoughtbot, the makers of Clearance, Shoulda, & Factory Girl:
http://thoughtbot.com/services/training

You received this message because you are subscribed to the "factory_girl" mailing list.
To post to this group, send email to factor...@googlegroups.com
To unsubscribe from this group, send email to
factory_girl...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/factory_girl?hl=en

Travis Pew

unread,
Apr 21, 2011, 1:38:01 PM4/21/11
to factory_girl
cache_classes is set to false.

I was using spork on my original project, which is where I thought the
problem might be. The freshly created rails project that I put on
github I installed in a new clean ruby environment without spork.

It seems likely to me that it's something in the interaction with
factory_girl and capybara or the rake_test driver, as I can't get the
error *without* capybara. To provide some additional detail, I never
see the AssociationTypeMismatch error in the *first* example/scenario
in the acceptance test, only in the second or later, and only if the
first is not empty but contains things like "visit '/items'". I
haven't figured out all the cases it occurs or doesn't occur, but with
my setup this acceptance test always causes the error:

feature "Test" do
background do
@user = Factory.create(:user)
end
scenario 'Scenario one' do
visit '/items'
end
scenario 'Scenario two' do
item = Factory.create(:item, :user => Factory.create(:user))
end
end

The only additionally specified gems to the base rails 3.0.7 and
sqlite3 are rspec-rails, capybara (from git), and factory_girl_rails.

I'm lost though about how to solve this issue since it seems to occur
in such a bare setup of factory_girl with capybara, but maybe I'll ask
the capybara folks if they have any insight.

Travis Pew

unread,
Apr 25, 2011, 6:36:25 PM4/25/11
to factor...@googlegroups.com
To help others since I've seen a couple similar questions elsewhere, I guess I misread what Joe was saying and that cache_classes needs to be set to true to use factory_girl with capybara. rack-test does unload constants if cache_classes = false, the default for the test environment.

-Travis

Michael Hellein

unread,
Apr 29, 2011, 1:02:49 PM4/29/11
to factory_girl
That seems like it could be an effective way to avoid the error, but
won't it get in the way of using spork/autotest if the classes are
cached?

Joe Ferris

unread,
Apr 29, 2011, 2:18:34 PM4/29/11
to factor...@googlegroups.com
Another option here is to defer factory definition loading until spork's each_run block. The factories depend on the models, and you don't want to load the models during the prefork phase. The easiest way to defer loading is to not require factory_girl by using :require => false in your Gemfile. Then just require factory_girl in your each_run block.

Keenan Brock

unread,
Apr 29, 2011, 2:24:46 PM4/29/11
to factor...@googlegroups.com
We defer loading factory girl using this method.
And it works quite well.

One thing to keep in mind.
Some other places in the code (e.g.: initializers) can unknowingly load the models.

And as I'm sure you know, this causes some odd errors (e.g.: the static methods are not reloaded in the models)

FWIW/
--Keenan

--Keenan

Michael Hellein

unread,
Apr 29, 2011, 3:57:25 PM4/29/11
to factory_girl
With factory_girl in the each_run block, I definitely still get that
error. I'm happy to forego spork and autotest for now, if it means
factories will work properly. Hopefully I'll track down what's causing
the repeated loading of the classes at some point, as it would be nice
to get everything working together.

On Apr 29, 2:18 pm, Joe Ferris <jfer...@thoughtbot.com> wrote:
> Another option here is to defer factory definition loading until spork's
> each_run block. The factories depend on the models, and you don't want to
> load the models during the prefork phase. The easiest way to defer loading
> is to not require factory_girl by using :require => false in your Gemfile.
> Then just require factory_girl in your each_run block.
>

Joe Ferris

unread,
Apr 29, 2011, 4:15:52 PM4/29/11
to factor...@googlegroups.com
Did you also make sure that you don't require factory_girl *before* the each_run block? By default, it gets loaded with everything in your Gemfile when Rails requires dependencies for the test environment.

Michael Hellein

unread,
Apr 29, 2011, 4:36:18 PM4/29/11
to factory_girl
Yep, I added the :require => false parameter in the Gemfile.

On Apr 29, 4:15 pm, Joe Ferris <jfer...@thoughtbot.com> wrote:
> Did you also make sure that you don't require factory_girl *before* the
> each_run block? By default, it gets loaded with everything in your Gemfile
> when Rails requires dependencies for the test environment.
>

Joe Ferris

unread,
Apr 29, 2011, 4:43:01 PM4/29/11
to factor...@googlegroups.com
It's possible that something else is loading factory_girl, or something else is loading your model before the pre_fork block. You can try adding puts statements to the specific files that you're having trouble reloading, or you could try running spork with -d to get more information on when things are being loaded.

Michael Hellein

unread,
Apr 29, 2011, 4:49:55 PM4/29/11
to factory_girl
I think I know what it is - all that's in my Gemfile is
factory_girl_rails. I should have factory_girl there explicitly as
well. I'm giving it a try now.

On Apr 29, 4:43 pm, Joe Ferris <jfer...@thoughtbot.com> wrote:
> It's possible that something else is loading factory_girl, or something else
> is loading your model before the pre_fork block. You can try adding puts
> statements to the specific files that you're having trouble reloading, or
> you could try running spork with -d to get more information on when things
> are being loaded.
>

Michael Hellein

unread,
Apr 29, 2011, 4:56:30 PM4/29/11
to factory_girl
Alas, no dice there.

Keenan Brock

unread,
Apr 29, 2011, 8:51:40 PM4/29/11
to factor...@googlegroups.com
Hi Michael,

I'm not sure how it works for me, but I only have:

Gemfile:

group :test do
  gem 'factory_girl', '1.2.3', :require => false
  #NOTE: no gem 'factory_girl_rails'
  gem 'spork', '0.8.4'
  gem 'spork-testunit', '0.0.3'
end

config/initializer/sporkless.rb

using_spork = defined?(Spork) && Spork.using_spork?
unless using_spork
  if Rails.env.test? || Rails.env.cucumber?
    require 'factory_girl'
  end
end


Hope that helps

--Keenan

--Keenan

Jonas Nielsen

unread,
Apr 30, 2011, 7:31:23 AM4/30/11
to factory_girl
I'm also experiencing the issue using spork.
putting , :require => false in my gemspec and require 'factory_girl'
in the each_run solves the issue, but only for the first run.

Any ideas to how to make it work continuously?

Travis Pew

unread,
May 2, 2011, 3:06:19 PM5/2/11
to factor...@googlegroups.com
I have been using it with spork since I determined that I had to set cache_classes to true to prevent errors.

In addition to require 'factory_girl_rails' in my each_run block, I also put at the beginning of the block to force unloading of the constants before I require factory_girl_rails:

ActiveSupport::Dependencies.clear

This seems to be sufficient for me, maybe it'll work for others?

Zach Moazeni

unread,
May 9, 2011, 9:28:02 AM5/9/11
to factor...@googlegroups.com
Travis, here was my solution:

1) Keep "cache_classes = true"
2) Don't have bundler require factory_girl_rails for you: "gem 'factory_girl_rails', :require => false"
3) put this at the top of spec_helper.rb and env.rb:

require 'factory_girl_rails'
Spork.trap_class_method(::Factory, :find_definitions)

However I ran into an issue where FactoryGirl loads constants in a slightly different way than Rails. If you have a class named "Foo::Bar" and get odd constant undefined errors with for Bar (not Foo::Bar), change your factories from a stringified version of the class to the literal class:

Factory.define :foo_bar, :class => "Foo::Bar" {|f| .... } # FactoryGirl chokes on me with this
Factory.define :foo_bar, :class => Foo::Bar {|f| .... } # This doesn't use FactoryGirl's constant loading.

I put together a patch to fix these constant loading issues, but I can't isolate the red/green scenario. http://groups.google.com/group/factory_girl/browse_thread/thread/8da599f731e475d7 https://github.com/zmoazeni/factory_girl/commit/457c667ca285a53960fc60ab97c8a2c364764673

--
Zach

Reply all
Reply to author
Forward
0 new messages