如何存根活动记录关系以使用rspec测试where子句?

时间:2014-11-05 17:27:48

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

我有一个看起来像这样的课程:

class Foo < ActiveRecrod::Base
  has_many :bars

  def nasty_bars_present?
    bars.where(bar_type: "Nasty").any?
  end

  validate :validate_nasty_bars
  def validate_nasty_bars
    if nasty_bars_present?
      errors.add(:base, :nasty_bars_present)
    end
  end
end

在测试#nasty_bars_present?我的方法就是写一个rspec测试来存根吧关联,但允许自然执行的地方。类似的东西:

describe "#nasty_bars_present?" do
  context "with nasty bars" do
    before { foo.stub(:bars).and_return([mock(Bar, bar_type: "Nasty")]) }
    it "should return true" do
      expect(foo.nasty_bars_present?).to be_true
    end
  end
end

上面的测试给出了关于没有数组方法的错误。我如何包装模拟以便哪里将适当执行?

谢谢!

1 个答案:

答案 0 :(得分:5)

对于RSpec 2.14.1(它也适用于RSpec 3.1),我会尝试这个:

describe "#nasty_bars_present?" do
  context "with nasty bars" do
    before :each do
      foo = Foo.new
      bar = double("Bar")
      allow(bar).to receive(:where).with({bar_type: "Nasty"}).and_return([double("Bar", bar_type: "Nasty")])
      allow(foo).to receive(:bars).and_return(bar)
    end
    it "should return true" do
      expect(foo.nasty_bars_present?).to be_true
    end
  end
end

这样,如果您在没有where语句中的特定条件的情况下调用bars.where(bar_type: "Nasty"),则不会使用bar_type: "Nasty"将条形图加倍。它可以重复用于将来模拟条形图(至少对于返回单个实例,对于多个实例,您将添加另一个实例)。