为什么ActiveRecord在查询同一条记录时会创建不同的ruby对象?

时间:2018-05-18 21:56:39

标签: unit-testing activerecord rspec

我正在尝试使用FactoryBot在RSpec中测试我的Rails模型中的命名范围。我正在创建几个记录,其中只有一个记录返回。

RSpec.describe GemNamespace::GemModel, type: :model do

  before(:all)
    FactoryBot.create(:gem_model, :trait1)  # id 1
    FactoryBot.create(:gem_model, :trait2)  # id 2
    FactoryBot.create(:gem_model, :trait3)  # id 3
  end

  let(:included_record) { GemNamespace::GemModel.find 1 }

  describe 'my_named_scope' do
    it 'returns only records matching the conditions' do
      scope_results = GemNamespace::GemModel.my_named_scope
      expect(scope_results).to contain_exactly(included_record)
    end
  end

end

测试失败,因为即使included_recordscope_results中唯一的记录,一些调试显示included_record实际上是一个不同于结果中的对象的Ruby对象某些原因。因此, contains_exactly 会失败。

我已经在大量模型上完成了这样的范围测试,并且它始终有效。与此问题的唯一区别是模型是在gem中定义的,我通过在Rails应用程序中将命名范围添加到其中来扩展其功能。

我错过了什么?为什么它只对这个模型表现如此?

如果重要:

  
      
  • Ruby 2.5.0
  •   
  • Rails 5.1.5
  •   
  • rspec 3.7.0
  •   
  • rspec-rails 3.7.2
  •   
  • factory_bot(_rails)4.8.2
  •   

更新:我会把它放在这里,而不是编辑上面的内容。我实际上测试的是数据库视图而不是表。视图没有唯一的ID列,因此我实际上并不是在GemNamespace::GemModel.find 1上面,而是where(column: <condition value>)

1 个答案:

答案 0 :(得分:0)

我通过解决方法解决了这个问题。我不太了解Rails的内部结构,但似乎没有id列的数据库视图(和相应的模型)搞砸了(即,创建了单独的Ruby对象) 。所以我只是比较了两个对象的所有值&#34;手动&#34;

# As a workaround, we're just gonna convert them both to Ruby hashes using
# the #as_json method, and compare those instead.

expect(scope_results.as_json).to contain_exactly(included_record.as_json)