AssociationTypeMismatch 和 FactoryGirl

发布于 2024-10-19 21:00:53 字数 521 浏览 0 评论 0原文

这最近引起了一些挫折......

似乎在我的黄瓜测试中使用工厂,在某些情况下会导致 AssociationTypeMismatch 错误,例如:

MyModel(#65776650)预期,得到 MyModel(# 28190030) (ActiveRecord::AssociationTypeMismatch)

这些似乎在存在关联引用时发生 - 就好像工厂创建的对象与真实对象不同一样。有关更多详细信息,请参阅此问题: Cucumber 重复类问题:AssociationTypeMismatch

我一直在逐渐改变工厂调用真实的 Model.create 或 mock_model 调用。继续使用Factory Girl就好了……我想知道我是否做错了什么?

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

萌无敌 2024-10-26 21:00:53

我在 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

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
美煞众生 2024-10-26 21:00:53

如果 ActiveSupport 卸载并重新加载您引用的常量,似乎会发生这种情况。
我在 Rspec/Capybara 上也经历过同样的事情,有帮助的是不同的事情的混合:

  • 确保你在测试环境(config/environments/test.rb)中将 cached_classes 设置为 false 在你
  • 的 gemspec 中,尝试替换 require ' factory_girl_rails' 和 'factory_girl'

我正在使用 Spork (测试服务器),这似乎使得这个事情变得越来越困难。
如果您使用的是测试服务器,请评估是否应该放置 ', :require =>;在 gemspec 中的factory_girl 之后为 false。

此 Google 网上论坛帖子也涵盖了该主题,

请告知我们如果其中有任何帮助的话。

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.

风流物 2024-10-26 21:00:53

如果您使用 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

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
歌枕肩 2024-10-26 21:00:53

发生这种情况是因为按照 Spork 的要求,cache_classes 为 false。 Capybara 会为每个请求重新加载 Rails 类(或者,正确地说,Rails 的重新加载器中间件会这样做,这在正常测试中是不需要的),这让工厂感到害怕(确切的原因,我不确定)。您可以重新加载它们,或者只是在 Spork 之外运行您的 Capybara 规范。

因此,您需要两件事:仅在 Spork 之外运行 Capybara,并仅针对 Spork 将 cache_classes 设置为 false。

为了只在 Spork 之外运行 Capybara,我有一个 Guardfile,它运行 Spork 之外的规范/请求中的规范以及 Spork 内部的其他规范:

https://gist.github.com/1731900

然后,在 config/environments/test.rb 中:

config.cache_classes = !ENV['DRB']

你的 Capybara 规格会慢一些,因为它们需要启动轨道,但一切都会正常工作。

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.

眼睛会笑 2024-10-26 21:00:53

我在重新加载工厂定义方面取得了一些成功,尝试如下操作:

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

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
亚希 2024-10-26 21:00:53

当我将由其他工厂继承的“class”选项传递给我的工厂时,我遇到了这个问题:

factory :draft_resource, :class => Resource do

factory :resource, :parent => :draft_resource do

我能找到的唯一解决方案就是不这样做。

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.

深海夜未眠 2024-10-26 21:00:53

我遇到了同样的问题,并花了大约十个小时尝试该线程和网络上其他地方的每个解决方案。我开始删除大量代码,试图使其尽可能接近我的另一个应用程序,在该应用程序中我无法重现问题。最后,我在 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

一个 sign_in 辅助函数,旨在在控制器和请求规范中工作。确实如此——只是不是用勺子。当我删除水豚助手后,问题就解决了:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文