如何使用rspec模拟测试方法的救援块3.3

时间:2015-08-20 20:28:50

标签: ruby-on-rails ruby rspec rspec3 rspec-mocks

帮助我完成测试通过:

以下是一些rspec代码的示例

class User
  attr_accessor :count

  def initialize
    @count = 0
  end

  # sometimes raises
  def danger
    puts "IO can be dangerous..."
  rescue IOError => e
    @count += 1
  end

  #always raises
  def danger!
    raise IOError.new    
  rescue IOError => e
    @count += 1
  end
end

describe User do  
  describe "#danger!" do
    it "its rescue block always increases the counter by one" do
      allow(subject).to receive(:'danger!')

      expect {
        subject.danger!
      }.to change(subject, :count).by(1)
    end
  end

  describe "#danger" do
    context "when it rescues an exception" do
      it "should increase the counter" do
        allow(subject).to receive(:danger).and_raise(IOError)

        expect {
          subject.danger
        }.to change(subject, :count).by(1)
      end      
    end
  end
end

我还在其中创建了fiddle这些测试,因此您可以让它们通过。请帮我测试方法的救援块!

背景

我原来的问题是这样的:

我有一个方法,如下所示:

def publish!(resource)
  published_resource = resource.publish!(current_project)

  resource.update(published: true)

  if resource.has_comments?
    content = render_to_string partial: "#{ resource.class.name.tableize }/comment", locals: { comment: resource.comment_content_attributes }

    resource.publish_comments!(current_project, published_resource.id, content)
  end

  true

  rescue Bcx::ResponseError => e
    resource.errors.add(:base, e.errors)

    raise e
  end

我想测试resource.errors.add(:base, e.errors)实际上是在资源中添加错误。更一般地说,我想用方法测试救援块。

所以我想写代码,

it "collects errors" do 
  expect{ 
    subject.publish!(training_event.basecamp_calendar_event)
  }.to change(training_event.errors.messages, :count).by(1)
end

当然,这会引发错误,因为我正在救援区重新加注。

我已经看到了一些使用旧something.stub(:method_name).and_raise(SomeException)的答案,但是rspec抱怨这种语法已被弃用。我想使用Rspec Mocks 3.3allow语法,但我很难过。

2 个答案:

答案 0 :(得分:3)

allow(something).to receive(:method_name).and_raise(SomeException)

将是新的allow语法。查看the docs以供参考。

答案 1 :(得分:0)

我误解了allow语法的实际含义。因此,要使我的示例规范通过,我需要这样做:

describe "#danger" do
  context "when it rescues an exception" do
    it "should increase the counter" do
      allow($stdout).to receive(:puts).and_raise(IOError) # <----- here

      expect {
        subject.danger
      }.to change(subject, :count).by(1)
    end      
  end
end

我正在捣乱的不是方法或主题,而是可能引起的对象。在这种情况下,我将$stdout存根,以便提升。

这是规范传递的另一个fiddle