1

您如何测试自定义 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比这个小例子复杂得多,这就是我想测试它的原因。在一个美好的世界里,我会把这个逻辑提取到一个助手中并测试这个助手,但现在现场测试是紧迫和有用的。

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

4

1 回答 1

2

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

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被调用并返回虚拟哈希:

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是如何做到的

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

  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
于 2021-01-08T10:26:13.587 回答