【问题标题】:Stub ActiveRecord::Relation with ActiveRecord objects存根 ActiveRecord::Relation 与 ActiveRecord 对象
【发布时间】:2014-01-25 00:35:08
【问题描述】:

我不是在测试 Rails 应用程序。只是把它排除在外。

我正在测试一个连接到相对活跃的服务器的库,通过时间戳限制记录。这些返回的记录随着时间​​的推移而变化,使测试其他限制变得更加复杂。我需要删除 ActiveRecord::where 方法以返回我自己与我创建的对象的自定义关系以满足我需要的标准。

类似

relation = double(ActiveRecord::Relation)
relation.stub(:[]).and_return( [MyClass.new(...), MyClass.new(...), ...] )
MyClass.stub(:where).and_return( relation )

是我想要的,但这不起作用。我需要它是ActiveRecord::Relation,因为我需要能够在代码中的对象上调用ActiveRecord::whereActiveRecord::select


编辑 2014-01-28

在 lib/call.rb 中

class Call < ActiveRecord::Base
  class << self
    def sales start_time, end_time
      restricted_records = records(start_time, end_time, :agent_id)
      #other code
    end

    #other methods

    private

      def records start_time, end_time, *select
        # I'm leaving in commented code so you can see why I want the ActiveRecord::Relation object, not an Array
        calls = Call.where("ts BETWEEN '#{start_time}' AND '#{end_time}'") #.select(select)
        raise calls.inspect
          #.to_a.map(&:serializable_hash).map {|record| symbolize(record)}
      end
  end
end

在 spec/call_spec.rb 中

require 'spec_helper'
require 'call.rb'

describe Call do
  let(:period_start) { Time.now - 60 }
  let(:period_end) { Time.now }

  describe "::sales" do
    before do
      relation = Call.all
      relation.stub(:[]).and_return( [Call.new(queue: "12345")] )
      Call.stub(:where).and_return( relation )
    end

    subject { Call.sales(period_start, period_end) }

    it "restricts results to my custom object" do
      subject
    end
  end
end

测试输出:

RuntimeError:
  #<ActiveRecord::Relation [ #an array containing all the actual Call records, not my object ]>

【问题讨论】:

    标签: ruby activerecord rspec mocking relation


    【解决方案1】:

    ActiveRecord::Relation 是一个类,:[] 是该类的实例方法。您正在为类本身的方法存根,因此任何 Rails 代码都不会调用它。

    如果您希望 MyClass.where 返回仅包含 :[] 存根的关系,则必须首先创建一个 Relation 实例,如下所示:

    relation = MyClass.all
    relation.stub(:[]).and_return( [MyClass.new(...), MyClass.new(...), ...] )
    MyClass.stub(:where).and_return( relation )
    

    但是,请注意,为了在此上下文中访问您返回的数组,您需要执行以下操作:

    MyClass.where("ignored parameters")["ignored parameters"]
    

    此外,如果您随后在 relation 上调用 where,您将返回一个 newRelation 实例,该实例将不再被存根。

    【讨论】:

    • 感谢您的回复,但这只是返回初始的MyClass.all 关系,而不是我的存根回复。我应该使用不同的方法吗?
    • 当你说“this”只是返回最初的MyClass.all,你到底指的是什么?
    • 抱歉,当我的测试运行时,调用 MyClass.where(args args args) 它返回最初从 MyClass.all 返回的集合,而不是您在第 2 行编写的存根集合。:[] 是正确的方法吗?跨度>
    • 它返回与 :[] 方法存根的 MyClass.all 关系,这就是您的问题所说的它想要做的事情。如果您将 :[] 方法发送到该对象(即我的回答说您需要这样做),您将获得您指定的数组。至于这是否是存根的“正确”方法,我无法为您回答,因为我不知道您希望 Relation 发挥作用的所有不同方式。
    • 嗯。好吧,这不是这段代码对我的表现。我将这些行复制到我的编辑器中,更改为我的班级名称并运行测试。它正在返回所有记录,而不是我的受限收藏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多