我想编写一个 RSpec 测试来验证,如果我的 Sinatra 驱动的 API 中发生 500 错误,该错误将被 Sinatra error
定义捕获并以 JSON 格式返回给客户端。也就是说,它不会返回一些 HTML 错误页面,而是返回如下 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 错误?
当面对这样的情况时,我通常做的是分开关注点,并将逻辑移出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
然后,您可以使用此代码使模型或用于实际生成响应的任何其他类/函数引发错误,使用以下规范:
# 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
使用 halt
方法:
require 'sinatra'
get '/' do
halt 500, {
success: 'false',
response: 'Internal server error'
}.to_json
end