我有两节课:

1.Sale是ActiveRecord的子类;它的工作是将销售数据持久保存到数据库中。

class Sale < ActiveRecord::Base
  def self.total_for_duration(start_date, end_date)
    self.count(conditions: {date: start_date..end_date})
  end
  #...
end

2.SalesReport是一个标准的Ruby类;它的工作是生成和绘制有关Sales的信息。
class SalesReport
  def initialize(start_date, end_date)
    @start_date = start_date
    @end_date = end_date
  end

  def sales_in_duration
    Sale.total_for_duration(@start_date, @end_date)
  end
  #...
end

因为我想使用TDD并且希望我的测试运行得非常快,所以我为SalesReport编写了一个规范,该规范不会加载Rails:
require_relative "../../app/models/sales_report.rb"

class Sale; end
# NOTE I have had to re-define Sale because I don't want to
# require `sale.rb` because it would then require ActiveRecord.

describe SalesReport do
  describe "sales_in_duration" do
    it "calls Sale.total_for_duration" do
      Sale.should_receive(:total_for_duration)
      SalesReport.new.sales_in_duration
    end
  end
end

当我运行bundle exec rspec spec/models/report_spec.rb时,此测试可工作为

但是,当我使用错误bundle exec rake spec运行superclass mismatch for class Sale (TypeError)时,此测试失败。我知道错误正在发生,因为Tap是由sale.rb和内联在规范中定义的。

所以我的问题是,如果未定义某个类,是否可以对它进行Stub(或Mock或Double)处理? 这将允许我删除内联的class Sale; end,感觉就像是一个hack。

如果不是,我该如何设置测试以使它们无论我运行bundle exec rspec还是bundle exec rake spec都能正确运行?

如果没有,我编写快速测试的方法是否错误?

最后,我不想使用Spork。谢谢!

最佳答案

RSpec最近添加的stub_const是专门为以下情况设计的:

describe SalesReport do
  before { stub_const("Sale", Class.new) }

  describe "sales_in_duration" do
    it "calls Sale.total_for_duration" do
      Sale.should_receive(:total_for_duration)
      SalesReport.new.sales_in_duration
    end
  end
end

您可能还想使用rspec-fire代替Sale来使用测试 double ,它会在加载了真正的Sale类的情况下运行测试时(例如,在运行测试套件时)自动检查真正的Sale类上存在的所有模拟/ stub 方法。 :
require 'rspec/fire'

describe SalesReport do
  include RSpec::Fire

  describe "sales_in_duration" do
    it "calls Sale.total_for_duration" do
      fire_replaced_class_double("Sale")
      Sale.should_receive(:total_for_duration)
      SalesReport.new.sales_in_duration
    end
  end
end

如果在真实的total_for_duration类上重命名Sale,则在模拟该方法时rspec-fire将给您一个错误,因为该方法在真实的类中不存在。

关于ruby - 带有和不带有Rails的快速(Rspec)测试,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13030514/

10-11 22:33