ruby - Stub ActiveRecord::Relation with ActiveRecord 对象

标签 ruby activerecord rspec mocking relation

我不是在测试 Rails 应用程序。只是解决这个问题。

我正在测试一个连接到相对活跃的服务器的库,按时间戳限制记录。这些返回的记录随着时间​​的推移而变化,使得测试其他限制变得更加复杂。我需要 stub 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 ]>

最佳答案

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

如果您希望 MyClass.where 返回仅包含 :[] stub 的关系,您必须首先创建一个 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,您将返回 Relation实例它将不再被 stub 。

关于ruby - Stub ActiveRecord::Relation with ActiveRecord 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21344992/

相关文章:

ruby - 与 "unexpected unary+"之后的空格相关的奇怪语法错误 `+`

ruby - 将 TESTOPTS ="-v"设置为 `rake test` 有什么意义?

mysql - 仅获取今天在 laravel 中创建的记录

ruby - 在 Ruby 中作为常量的符号

ruby-on-rails - RSpec allow_any_instance_of 在请求测试中不起作用

ruby-on-rails - 使用 Ruby Spreadsheet gem,我可以将单元格格式设置为货币吗?

Ruby Shoes 不适用于符号

ruby-on-rails - Rails ActiveRecord 助手查找方法不急于加载关联

php - Yii Active Record 在不同表的命名范围内添加多个条件

ruby-on-rails - 在 rspec 请求规范中跨多个获取请求维护 session