RSpec失败,因为它认为ActiveRecord对象不相等

时间:2011-09-16 00:36:19

标签: ruby-on-rails ruby rspec factory-bot

非常简单的规范......

@post.user.should == @user

Spec失败,即使两个对象除了object_id之外在各方面都相同。如果它们的id相同,则ActiveRecord对象应该等于(==)。使用factory_girl创建对象。我已经确认这两个对象都不是“.new_record?”。比较@ post.user.id和@ user.id有效。

更多的是行为不一致。这些测试正在进行,现在尽管没有变化,但它们仍然失败。

  • Rails 3.1
  • rspec的-2.6
  • factory_girl-2.0.5
  • factory_girl_rails-1.1.0
  • jruby 1.6.4(ruby-1.9.2-p136)
  • 的windows7

我通常使用spork,但这也没有spork。

更多细节:

在ActiveRecord :: Base

中,有问题的代码行似乎如下
def ==(comparison_object)
  super ||
    comparison_object.instance_of?(self.class) &&
    id.present? &&
    comparison_object.id == id
end

具体来说,“instance_of?”检查失败的时候不应该。我检查了两个对象的类层次结构。但是,当我检查每个对象的class.id时,它们并不相同。

此外,行为取决于我运行的命令......

jruby -S bundle exec rspec spec (FAILS)
jruby -S bundle exec rspec spec\models (PASSES)
jruby -S bundle exec rspec spec\models\post_spec.rb (PASSES)

在我的environment / test.rb文件中设置cache_classes = true似乎解决了这个问题,但我不认为这是必要的。

2 个答案:

答案 0 :(得分:1)

这最终真的很傻。问题是我在/ spec / integration中进行了集成测试而不是/ spec / requests。 Rspec / Rails只在一组特定的目录中执行加载魔术,但会从所有目录运行所有测试(导致双重加载)。

答案 1 :(得分:0)

由于活动记录的工作方式,这些对象具有不同的object_id。在你给出的例子中

@post.user.should == @user

@ post.user和@user是内存中完全独立的对象。即使它们是同一个类的实例,并且它们具有相同的id字段,它们也永远不会具有相同的object_id(显然只要cache_classes = false)。

其他ORM(例如数据映射器)使用身份映射处理此问题。在Rails 3.1中,活动记录中有实验性身份映射支持,但默认情况下禁用它。

有关详细信息,请参阅identity_map.rb