【问题标题】:Spec for class method - preserving order and returns an ActiveRecord relation类方法规范 - 保留顺序并返回 ActiveRecord 关系
【发布时间】:2019-12-11 11:06:45
【问题描述】:

Rails 上的新手,目前正在学习如何处理类方法、范围和规范... 最初这是作为模型中的作用域编写的,但它看起来有点臃肿,所以我把它拿出来并做成如下的类方法:

class OrderedByIds

  scope :for_ids_with_order, lambda { |ids|
    order = sanitize_sql_array(
      ["position((',' || id::text || ',') in ?)", ids.join(',') + ',']
    )
    where(id: ids).order(order)
  }

end

#用法:

 OrderedByIds.for_ids_with_order([1, 3, 2])

对此类方法进行单元测试的最佳方法是什么?

【问题讨论】:

  • 我不明白你做了什么。这曾经是模型中的一个方法,现在你已经把它移到另一个类中了吗?你希望这如何工作?你能提供更多的上下文吗?根据您提供的有限信息,我认为这没有意义——您可以将该方法移动到 module 中,从而将 included 放入模型中,但我不这样做不知道您希望如何将它用作这样的独立类。
  • 您可以像任何其他方法一样对其进行测试。例如,expect(MyModel.for_ids_with_order).to eq (...)。但同样,如果不了解如何使用此方法的更广泛背景,我不可能编写一个有效的测试用例。
  • “类方法”并不意味着你将一个代码块移动到它自己的类中。这意味着您在类而不是类的实例上定义方法(请参阅method scopes)。为了将类的一部分提取到单独的模块中,Rails 提供了ActiveSupport::Concern
  • @Stefan 最初,这是作用域用法,我如何制作类方法?rubyfiddle.com/riddles/653c0
  • @drifterOcean19 我上面评论中的“方法范围”链接包含一个类方法的示例。你通常只在类体内写def self.method_name

标签: ruby-on-rails ruby unit-testing rspec rspec-rails


【解决方案1】:

您不能真正对此进行单元测试,因为它与数据库紧密耦合。 所以 Rails 模型测试并不是真正的单元测试。

因此,您可以对其进行测试,这非常简单。 (我假设您使用的是 FactoryBot 并且您的 rspec 是 Aggregating failures

let!(:order) { create(:order) }
let!(:other_order) { create(:order) }

specify do
   expect(describe_class.for_ids_with_order([order.id])).to eq [order]
   expect(describe_class.for_ids_with_order([other_order.id])).to eq [other_order]
end

然后,您可以执行另一个测试排序的上下文:我将创建 3 个或更多项目,具有指定的位置并做出类似上述的预期,但您期望具有特定顺序的少数项目数组(我'不是 100% 确定 "position((',' || id::text || ',') in ?)" 在那里做什么,因此没有例子。但这应该让你继续)。

顺便说一句。如果它是一个范围,我会以完全相同的方式对其进行测试。

编辑:我错过了关于重新调整 AR 关系的部分。

expect(describe_class.for_ids_with_order([order.id])).to be_a(ActiveRecord::Relation)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多