【问题标题】:How do I test the rescue block of a method with rspec mocks 3.3如何使用 rspec mocks 3.3 测试方法的救援块
【发布时间】:2015-08-20 20:28:49
【问题描述】:

帮助我通过这个测试:

这是一些 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 语法,但我很难。

【问题讨论】:

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


    【解决方案1】:
    allow(something).to receive(:method_name).and_raise(SomeException)
    

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

    【讨论】:

    • 这没有回答问题,即“我如何测试方法的救援块”。此外,您链接到 2.14 文档。请参阅我的问题以获取相关 3.3 文档的链接。
    【解决方案2】:

    我误解了 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 以便 put 会加注。

    这是另一个 fiddle 规范正在通过。

    【讨论】:

    • 不要迂腐,但@p4sh4 大约在 13 小时前回答了您的问题。
    • 我认为他没有!他提供了一个文档链接,我自己也提供了一个链接。他包含了allow 语法的示例,但没有说明如何使用它。看了他的回答后,我感觉自己装备好不好。只有在构建了这个最小的例子之后,我才能自己解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多