ruby-on-rails 如何为返回集合的函数创建测试?

jaql4c8m  于 2023-01-27  发布在  Ruby
关注(0)|答案(1)|浏览(111)

我正在实现一个函数的测试,该函数通过查询选择返回一个集合,此函数select_collection希望使用规范进行测试,因此我尝试这样进行模拟

let(:scenaries) { [
    double(: organizational_unit, section_id: section.id, type_id: type.id),
    double(: organizational_unit, section_id: section.id, type_id: type.id)
  ] }

现在我想测试这个函数,比较scenaries和select_collection的结果

def select_collection
    OrganizationalUnit.where('section.id = ? ...)
  end
mbyulnm0

mbyulnm01#

你不能用那种方式模仿对象...一个示例双精度数的 * 数组 * 和一个对象集合不是一回事,而且我认为你的双精度数甚至没有被示例化(你没有在你的代码片段中引用'scenaries',你使用的是let而不是let!,var正在被延迟加载)。
首先,select_collection背后的意图是什么?命名听起来像是选择整个集合,但这对于内置的OrganizationalUnit.all查询方法来说是多余的。如果要过滤集合(代码片段中确实有where),那么最好使用更具体的名称。
第二,你的代码片段将select_collection定义为一个示例方法(def select_collection),但是你的测试将它作为一个类方法调用(需要将它定义为def self.select_collection),但是如果你想要做的只是从那个模型返回一个经过过滤的对象集合,你应该将它定义为一个查询作用域(* 而不是 * 一个类/示例方法):https://guides.rubyonrails.org/active_record_querying.html#scopes
第三,您正在测试查询对象,您应该将它们创建为实际的测试对象,并编写如下所示的测试:

describe '.some_scope_name' do
  subject(:result) { OrganizationalUnit.some_scope_name }

  let!(:expected_units) { 
    create_list :organizational_unit, 3,
      some_attribute: true
  }
  let!(:excluded) { 
    create :organizational_unit, 
      some_attribute: false

  it 'fetches expected collection' do
    expect(result).to contain_exactly(expected_units)
  end
end

使用let!可以确保在我们的示例中触发查询之前,对象已经存在于我们的测试DB中。
推荐阅读:

相关问题