Ruby on rails 铁路,包括吗?当它不应';T

Ruby on rails 铁路,包括吗?当它不应';T,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我正在RSpec中测试我的ActiveRecord模型,我试图通过实例化模型而不是创建FactoryGirl模型来加快测试速度,但是ActiveRecord::Associations::CollectionProxy.include?在我期望false时返回true 我正在测试的代码是调度模型中的这个方法,它被传递一个位置模型实例的参数 def available_at_location(location) locations.include?(location) end 测试是 bef

我正在RSpec中测试我的ActiveRecord模型,我试图通过实例化模型而不是创建FactoryGirl模型来加快测试速度,但是
ActiveRecord::Associations::CollectionProxy.include?
在我期望
false
时返回
true

我正在测试的代码是调度模型中的这个方法,它被传递一个位置模型实例的参数

def available_at_location(location)
  locations.include?(location)
end
测试是

before do
  subject.locations = [location_b]
end

it 'returns false' do
  result = subject.available_at_location(location_a)

  expect(result).to be(false)
end
当我用FactoryGirl创建
location\u a
location\u b
时,测试通过,
include?
返回
false
,但当我用此代码实例化
location\u a
location\u b
时,测试失败并包括?返回
true

let(:location_a) { Location.new(name: 'London') }
let(:location_b) { Location.new(name: 'York') }
打印
location
表明它是一个包含
location\u b
的CollectionProxy,打印
location
参数表明它是
location\u a
,两者都具有正确的属性。并且,
include?
返回
true
是否传递了
location
参数

编辑:一些附加代码

这是定义主题的代码

subject { described_class.new(locations: [location_a]) }
这是FactoryGirl工厂的代码

require 'faker'

FactoryGirl.define do
  factory :location do
    name { Faker::Company.name }
    address { Faker::Address.street_address }
    city { Faker::Address.city }
    zipcode { Faker::Address.zip_code }
    landline { Faker::PhoneNumber.phone_number }
    association :organization
  end
end

注意:我尝试向构造函数提供一个组织(
Location.new(名称:'London',组织:Organization.new)
),但它不会更改输出。

CollectionProxy
根据模型的
id
比较模型,由于这两个记录都是新的,并且id==nil-
include?
返回
true

let(:location_a) { Location.new(name: 'London') }
let(:location_b) { Location.new(name: 'York') }

要使测试正常工作,您必须将模型保存到数据库(使用
create!
等等)

CollectionProxy
根据模型的
id
s比较模型,因为这两个记录都是新的,并且具有
id==nil
-
include?
返回
true

let(:location_a) { Location.new(name: 'London') }
let(:location_b) { Location.new(name: 'York') }

要使测试正常工作,您必须将模型保存到db(使用
create!
等等)

我已经找到了解决方案。我将在这里记录这一点,以防其他人有类似的问题。这些线路就是问题所在

subject { described_class.new(locations: [location_a]) }

before do
  subject.locations = [location_b]
end
当使用模型实例而不是FactoryGirl制作的完整DB模型时,ActiveRecord不会更新对CollectionProxies中项目的更改。就
位置而言
始终是
[location\u a]
,即使您将项目更改为
[location\u b]

解决方案是只指定一次属性。即

subject { described_class.new(locations: []) }

before do
  subject.locations = [location_b]
end
将每个上下文的before块中的位置设置为所需位置


我确信这与对Collection/CollectionProxy的引用有关,但我无法理解。

我已经找到了解决方案。我将在这里记录这一点,以防其他人有类似的问题。这些线路就是问题所在

subject { described_class.new(locations: [location_a]) }

before do
  subject.locations = [location_b]
end
当使用模型实例而不是FactoryGirl制作的完整DB模型时,ActiveRecord不会更新对CollectionProxies中项目的更改。就
位置而言
始终是
[location\u a]
,即使您将项目更改为
[location\u b]

解决方案是只指定一次属性。即

subject { described_class.new(locations: []) }

before do
  subject.locations = [location_b]
end
将每个上下文的before块中的位置设置为所需位置


我确信这与引用Collection/CollectionProxy有关,但我无法理解。

请提供主题工厂代码。我不确定您指的是主题的定义(我在任何时候都没有使用FG创建主题)还是该位置的FactoryGirl,但我在文章的编辑中提供了两者。请,提供你的主题工厂代码。我不确定你是指该位置的主题定义(我在任何时候都没有使用FG创建主题)还是FactoryGirl,但我在文章的编辑中提供了两者。我尝试在位置构造函数中提供一个
id
,但没有帮助。它是否只在模型保存到数据库时才起作用?编写只使用实例化对象而不使用保存对象的AR模型测试可能会令人沮丧。通常,您会遇到需要保存的对象(具有ID)的情况,而这是您没有预料到的。您可以尝试从模型中提取方法并将它们放入其他类中,在这些类中您可以在不与DB交互的情况下测试它们。在对代码进行了一些挖掘之后,对于内存中的记录,CollectionProxy不进行对象等价性而不是ID比较。我尝试在位置构造函数中提供一个
ID
,但没有任何帮助。它是否只在模型保存到数据库时才起作用?编写只使用实例化对象而不使用保存对象的AR模型测试可能会令人沮丧。通常,您会遇到需要保存的对象(具有ID)的情况,而这是您没有预料到的。您可以尝试从模型中提取方法并将它们放入其他类中,在这些类中您可以在不与DB交互的情况下测试它们。在对代码进行一些挖掘之后,对于内存中的记录,CollectionProxy不进行对象等价而不是ID比较。