在 Sinatra 中故意引发 500 个错误以测试它们的处理方式

Raising 500 errors deliberately in Sinatra in order to test how they are handled

我想编写一个 RSpec 测试来验证,如果在我的 Sinatra 支持的 API 中发生 500 错误,该错误将被 Sinatra error 定义捕获并以 JSON 格式返回给客户端。也就是说,它不是返回一些 HTML 错误页面,而是 returns JSON 这样以符合 API:

的其余部分
{
  success: "false",
  response: "Internal server error"
}

但是,我不确定如何在我的 Sinatra 应用程序中实际触发 500 错误,以便使用 RSpec 测试此行为。我找不到模拟 Sinatra 路由的方法,所以目前我最好的想法是这条故意导致 500 的路由。这感觉像是一个非常糟糕的解决方案:

get '/api/v1/testing/internal-server-error' do
  1 / 0
end

有没有办法模拟 Sinatra 路由,这样我就可以让 / 的路由处理程序块引发异常,从而触发 500?如果不是,是否有其他方法可以在我的应用程序中故意导致 500 错误?

使用halt方法:

require 'sinatra'

get '/' do
  halt 500, {
    success: 'false',
    response: 'Internal server error'
  }.to_json
end

面对这种情况,我通常做的是分离关注点,将逻辑移到 Sinatra get ... 块之外。然后,很容易对其进行存根并使其引发错误。

例如,给定此服务器代码:

# server.rb
require 'sinatra'

class SomeModel
  def self.some_action
    "do what you need to do"
  end
end

get '/' do
  SomeModel.some_action
end

然后您可以使用此代码来生成模型,或您正在使用的任何其他 class/function 实际生成响应,使用此规范引发错误:

# spec
describe '/' do
  context 'on error' do
    before do 
      allow(SomeModel).to receive(:some_action) { raise ArgumentError }
    end

    it 'errors gracefully' do
      get '/'
      expect(last_response.status).to eq 500
    end
  end
end

为了完整起见,这里有一个自包含文件,可以通过 运行 rspec thisfile.rb:

进行测试以演示此方法
# thisfile.rb
require 'rack/test'
require 'rspec'
require 'sinatra'

# server

class SomeModel
  def self.some_action
    "do what you need to do"
  end
end

get '/' do
  SomeModel.some_action
end

# spec_helper

ENV['APP_ENV'] = 'test'

module RSpecMixin
  include Rack::Test::Methods
  def app() Sinatra::Application end
end

RSpec.configure do |c|
  c.include RSpecMixin
end

# spec

describe '/' do
  context 'on error' do
    before do 
      allow(SomeModel).to receive(:some_action) { raise ArgumentError }
    end

    it 'errors gracefully' do
      get '/'
      expect(last_response.status).to eq 500
    end
  end
end