【问题标题】:Stubbing an exception, but evaluating normally (RSpec)存根异常,但正常评估(RSpec)
【发布时间】:2013-06-22 18:45:10
【问题描述】:

我正在尝试根据块的性能更新对象上的实例变量@status。这个块也调用另一个类。

def run
  @entries.keep_if { |i| valid_entry?(i) }.each do |e|
    begin
      unique_id = get_uniqueid e
      cdr_record = Cdr.find_by_uniqueid(unique_id).first
      recording = cdr_record.nil? ? NullAsteriskRecording.new : AsteriskRecording.new(cdr_record, e)
      recording.set_attributes
      recording.import
    rescue Exception => e
      fail_status
    end
  end
end

fail_status 是一个私有方法,将实例变量更新为:failed。通过破坏其他一些东西,我基本上已经验证了这段代码是有效的,但我也想要一个适当的测试。目前,我有以下内容:

context "in which an exception is thrown" do
  before do
    @recording = double("asterisk_recording")
    @recording.stub(:import).and_raise("error")
  end

  it "should set #status to :failed" do
    # pending "Update instance variable in rescue block(s) of #run"
    subject.run
    subject.status.should eq :failed
  end
end

但测试总是失败。 rescue 块永远不会被评估(我检查了 puts 语句,当我在 raise 语句中硬编码时会评估该语句)。我在这里使用double 功能是否错误?或者我是通过排除异常来完成自己的工作,所以rescue 块永远不会运行?

【问题讨论】:

    标签: ruby-on-rails exception mocking rspec2 stub


    【解决方案1】:

    您在 before 块中设置了 @recording,但您为 run 方法发布的代码不会使用该 @recording 实例,因此在 run 方法中调用 recording.import 不会引发异常。

    在您的 run 方法中,录制最终可以是 NullAsteriskRecording 或 AsteriskRecording 的实例。如果您知道这将是 AsteriskRecording 正如您当前的测试所暗示的那样,一种方法是将您的 before 块更改为以下内容:

    before do
      AsteriskRecording.any_instance.stub(:import).and_raise("error")
    end
    

    【讨论】:

    • 我的运气,就这么简单。谢谢!解释很好。