您如何在 Ruby 中测试自定义 Bugsnag meta_data?

How do you test custom Bugsnag meta_data in Ruby?

您如何测试自定义 Bugsnag meta_data(在 Ruby 中,使用 Rspec)?

我要测试的代码:

def do_something
  thing_that_could_error
rescue => e
  Bugsnag.notify(e) do |r|
    r.meta_data = { my_extra_data: "useful info" }
  end
end

我要写的测试:

context "when there's an error" do
  it "calls Bugsnag with my special metadata" do
    expect(Bugsnag).to receive(:notify) # TODO test meta_data values contain "my useful info"
    expect do
      do_something() # exception is thrown and rescued and sent to Bugsnag
    end.not_to raise_error
  end
end

我正在使用:

meta_data 变量中的数据比这个小例子要复杂得多,这就是我要测试它的原因。在一个美好的世界里,我会把那个逻辑提取到一个 helper 中并测试 helper,但是现在在原位测试是紧急和有用的。

我一直在查看 Bugsnag gem 的内部来解决这个问题(加上一些 Rspec-fu 来捕获各种内部状态和返回的数据)但在某些时候它是问互联网是个好主意。

由于元数据很复杂,我建议简化它:

def do_something
  thing_that_could_error
rescue => e
  Bugsnag.notify(e) do |r|
    r.meta_data = error_metadata(e, self, 'foo')
  end
end

# I assumed that you'd like to pass exception and all the context
def error_metadata(e, object, *rest)
  BugsnagMetadataComposer.new(e, object, *rest).metadata
end

现在您可以对 BugsnagMetadataComposer 进行单独测试,您可以完全控制(无需模拟)初始化它的方式,并测试 metadata 输出。

现在你只需要测试 BugsnagMetadataComposer 是否用你想要的对象实例化, metadata 被调用并且它 returns 虚拟哈希:

let(:my_exception) { StandardError.new } 
let(:mock_metadata) { Hash.new } 

before do
  # ensure thing_that_could_error throws `my_exception`
expect(BugsnagMetadataComposer)
  .to receive(new)
  .with(my_exception, subject, anything)
  .and_return(mock_metadata)
end

最难的部分是确保元数据已分配。为此,您可以稍微作弊,看看 Bugsnag gem is doing it

显然有一种叫做面包屑的东西:

  let(:breadcrumbs) { Bugsnag.configuration.breadcrumbs }

我猜它有所有的 Bugsnag 请求,最后一个在上面,所以你可以做类似于 https://github.com/bugsnag/bugsnag-ruby/blob/f9c539670c448f7f129a3f8be7d412e2e824a357/spec/bugsnag_spec.rb#L36-L40

的事情
specify do 
  do_something()

  expect(breadcrumbs.last.metadata).to eq(expected_metadata)
end

为了清楚起见,整个规范看起来有点像这样:

let(:my_exception) { StandardError.new } 
let(:mock_metadata) { Hash.new } 

before do
  # ensure thing_that_could_error throws `my_exception`
  expect(BugsnagMetadataComposer)
    .to receive(new)
    .with(my_exception, subject, anything)
    .and_return(mock_metadata)
end

specify do 
  do_something()

  expect(breadcrumbs.last.metadata).to eq(expected_metadata)
end