使用 RSpec 进行测试时,如何在 Sidekiq worker 中正确捕获错误?
How can I trap errors correctly in a Sidekiq worker when testing with RSpec?
我有一个相对简单的工人,使用 Excon 从互联网上抓取一些东西。我正在努力成为一名优秀的测试人员,并使用 Webmock 强制对 Internet 交互进行存根,这样我实际上是在测试代码应该根据各种存根交互执行的操作。
我注意到 RSpec 没有捕获 worker 内部发生的故障。这可能是我的代码,也可能是错误,我不确定。
这是一个简单的 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 的 perspec 角度来看没有错误,因为它在 worker 内部 captured/handled。如果您删除了救援,我预计测试会失败,正如您所期望的那样。相反,您可以检查测试以查看是否执行 returns 非零值才能通过。有帮助吗?
为了 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
我有一个相对简单的工人,使用 Excon 从互联网上抓取一些东西。我正在努力成为一名优秀的测试人员,并使用 Webmock 强制对 Internet 交互进行存根,这样我实际上是在测试代码应该根据各种存根交互执行的操作。
我注意到 RSpec 没有捕获 worker 内部发生的故障。这可能是我的代码,也可能是错误,我不确定。
这是一个简单的 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 的 perspec 角度来看没有错误,因为它在 worker 内部 captured/handled。如果您删除了救援,我预计测试会失败,正如您所期望的那样。相反,您可以检查测试以查看是否执行 returns 非零值才能通过。有帮助吗?
为了 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