Тестирование тайм-аута в синатре и рубине
Я подумал, что это будет просто, но у меня возникли проблемы с тестированием самоцвета в стойке. У меня есть базовый класс sinatra с конечной точкой, которая выполняет некоторую логику.
module MyModule
class MySinatra < Sinatra::Base
use Rack::Timeout
Rack::Timeout.timeout = 10
get '/dosomething' do
#do the normal logic.
end
end
end
Больше информации о стойке-тайм-ауте здесь. Я пытаюсь настроить тест, в котором я могу отправить запрос, который, как я знаю, займет более нескольких секунд, чтобы он не прошел.
Вот тест пока
require "test/unit"
require "mocha/setup"
require 'rack/timeout'
def test_rack_timeout_should_throw_timed_out_exception_test
Rack::Timeout.stubs(:timeout).returns(0.0001)
assert_raises TimeoutError do
get "/dosomething"
end
Rack::Timeout.unstub
end
Есть несколько способов сделать это, но я не уверен, как они будут реализованы
- Переопределите метод "/dosomething" как часть теста для {sleep 3}
- Сделайте то же самое, что и выше, но с библиотекой окурков или насмешек.
- вместо использования get "/dosomething" в тесте создайте ответ net::http, который будет держать запрос открытым.
Любые мысли по этому поводу будут очень цениться.
1 ответ
Прежде всего, ваш тест на самом деле не пройдет, потому что ошибка не передается тесту. Он поднимается только на стороне сервера. К счастью, стойка-тест обеспечивает 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