【问题标题】:How can I trap errors correctly in a Sidekiq worker when testing with RSpec?使用 RSpec 进行测试时,如何在 Sidekiq 工作人员中正确捕获错误?
【发布时间】:2020-11-17 22:15:52
【问题描述】:

我有一个相对简单的工作人员,它使用 Excon 从互联网上抓取一些东西。我正在努力成为一名优秀的测试人员,并使用 Webmock 强制对互联网交互进行存根,这样我实际上是在根据各种存根交互测试代码应该做什么。

我注意到 RSpec 没有捕捉到工人内部发生的故障。这可能是我的代码,也可能是错误,我不确定。

这是一个简单的 worker 示例(是的,我知道救援异常很糟糕,我会在接下来修复它):

  include Sidekiq::Worker
  sidekiq_options queue: 'fetch_article_content', retry: true, backtrace: true

  def perform(url)
    begin
      Excon.get(url)
    rescue Exception => e
      Rails.logger.warn("error: #{e}")
      nil
    end
  end
end

这是一个简化的 RSpec 测试:

      Sidekiq::Testing.inline!
      work = FetchArticleContentWorker.new
      work.perform("http://google.com")

启用 Webmock 后,这会导致 Excon 失败(在 test.log 文件中可见):

error: Real HTTP connections are disabled. Unregistered request: ...

但是,RSpec 认为这很好用:

.

Finished in 0.44487 seconds (files took 5.35 seconds to load)
1 example, 0 failures

我不确定我在这里做错了什么。我预计 Sidekiq perform 未能将 RSpec 视为失败,但事实并非如此。

  • 我没有正确捕捉到这个错误吗?
  • 我是否应该检查有关作业状态的某些内容,而不是期望 RSpec 在工作人员中捕获此错误?
  • 我应该完全做其他事情吗?

谢谢!

【问题讨论】:

    标签: rspec sidekiq webmock excon


    【解决方案1】:

    为了让 RSpec 看到异常,代码必须引发异常。

    您可以重新引发现有异常:

    def perform(url)
      begin
        Excon.get(url)
      rescue Exception => e
        Rails.logger.warn("error: #{e}")
        raise e
      end
    end
    

    您可以将现有异常包装在您自己的一个中:

    class MyFancyException < StandardError; end
    
    def perform(url)
      begin
        Excon.get(url)
      rescue Exception => e
        Rails.logger.warn("error: #{e}")
        raise MyFancyException.new(e)
      end
    end
    

    两者都有效。两者都需要一些类似于此的 RSpec:

    describe Worker do
      subject(:worker) { described_class.new }
    
      describe "#perform" do
        subject(:perform) { worker.perform }
    
        let(:url) { "https://google.com" }
    
        it "raises exception" do
          expect { perform(url) }.to raise_error(MyFancyException)
        end
      end
    end
    

    【讨论】:

      【解决方案2】:

      我认为从 rspec 的角度来看没有错误,因为它是在工作人员内部被捕获/处理的。如您所料,如果您取消了救援,我预计测试会失败。相反,您可以检查测试以查看 perform 是否返回非 nil 值才能通过。这有帮助吗?

      【讨论】:

        猜你喜欢
        • 2019-01-16
        • 2015-03-10
        • 2017-02-11
        • 2021-10-31
        • 2013-09-16
        • 1970-01-01
        • 2018-11-05
        • 1970-01-01
        • 2013-03-21
        相关资源
        最近更新 更多