ruby – 使用和不使用Rails进行快速(Rspec)测试

前端之家收集整理的这篇文章主要介绍了ruby – 使用和不使用Rails进行快速(Rspec)测试前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两节课:

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类;它的工作是生成和绘制有关销售的信息.

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并且类Sale(TypeError)的错误超类不匹配时,此测试失败.我知道错误正在发生,因为Tap是由sale.rb定义并在规范中内联.

所以我的问题是,如果没有定义该类,有一种方法可以将Stub(或Mock或Double)作为一个类吗?这将允许我删除内联类Sale;结束,这感觉就像一个黑客.

如果没有,如何运行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来使用测试双精度来自动检查真实Sale类中存在的所有模拟/存根方法在运行带有加载的真实Sale类的测试时(例如,当您运行测试套件时) :

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

如果在真正的Sale类上重命名total_for_duration,则在模拟方法时rspec-fire会给出错误,因为它在实际类中不存在.

猜你在找的Ruby相关文章