まず、エラーがテストに渡されないため、テストは実際には合格しません。サーバー側でのみ発生します。幸い、rack-testは、last_response.errors
エラーが発生したかどうかを確認する方法を提供します。したがって、私は上記のテストを次のように記述します。
def test_rack_timeout_should_throw_timed_out_exception
Rack::Timeout.stubs(:timeout).returns(0.0001)
get '/dosomething'
assert last_response.server_error?, 'There was no server error'
assert last_response.errors.include?('Timeout::Error'), 'No Timeout::Error raised'
Rack::Timeout.unstub
end
あとは、ルートをオーバーライドして遅い応答をシミュレートするだけです。最初はシンプルに見えましたが、手に取ってみると、それほどシンプルではないことに気づきました。私はたくさんいじって、ここでこれを思いついた:
class Sinatra::Base
def self.with_fake_route method, route, body
old_routes = routes.dup
routes.clear
self.send(method.to_sym, route.to_s, &body.to_proc)
yield
routes.merge! old_routes
end
end
メソッドに渡すブロック内で、一時的にルートのみを使用できるようになります。たとえば、次のようにして遅い応答をシミュレートできます。
MyModule::MySinatra.with_fake_route(:get, '/dosomething', ->{ sleep 0.0002 }) do
get '/dosomething'
end
get '/dosomething'
ブロックの内側は一時的なルートの定義ではなく、モックリクエストを実行するラックテストの方法であることに注意してください。実際のオーバーライドルートは、への引数の形式で指定されますwith_route
。
これは私が思いつくことができる最良の解決策ですが、これを解決するためのよりエレガントな方法を見たいと思います。
完全な動作例(Ruby 1.9.3.p385で実行):
require 'sinatra/base'
require 'rack/timeout'
module MyModule
class MySinatra < Sinatra::Base
use Rack::Timeout
Rack::Timeout.timeout = 10
get '/dosomething' do
'foo'
end
end
end
require 'test/unit'
require 'rack/test'
require 'mocha/setup'
class Sinatra::Base
def self.with_fake_route method, route, body
old_routes = routes.dup
routes.clear
self.send(method.to_sym, route, &body)
yield
routes.merge! old_routes
end
end
class Tests < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyModule::MySinatra
end
def test_rack_timeout_should_throw_timed_out_exception
Rack::Timeout.stubs(:timeout).returns(0.0001)
MyModule::MySinatra.with_fake_route(:get, '/dosomething', ->{ sleep 0.0002 }) do
get '/dosomething'
end
assert last_response.server_error?, 'There was no server error'
assert last_response.errors.include?('Timeout::Error'), 'No Timeout::Error raised'
Rack::Timeout.unstub
end
end
生成:
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips