Настройка Rack-Test для косвенного запуска сервера
Вот мое приложение стойки:
class MainAppLogic
def initialize
Rack::Server.start(:app =>Server, :server => "WEBrick", :Port => "8080")
end
end
class Server
def self.call(env)
return [200, {},["Hello, World"]]
end
end
При фактическом запуске он ведет себя как должен и возвращает "Hello World" всем запросам. У меня проблемы с тем, чтобы убедить рэк-тест работать с ним. Вот мои тесты:
require "rspec"
require "rack/test"
require "app"
# Rspec config source: https://github.com/shiroyasha/sinatra_rspec
RSpec.configure do |config|
config.include Rack::Test::Methods
end
describe MainAppLogic do
# App method source: https://github.com/shiroyasha/sinatra_rspec
def app
MainAppLogic.new
end
it "starts a server when initialized" do
get "/", {}, "SERVER_PORT" => "8080"
last_response.body.should be != nil
end
end
Когда я проверяю это, он не жалуется, что MainAppLogic
это не сервер в стойку, в частности, что он не отвечает на MainAppLogic.call
, Как я могу дать ему знать, чтобы игнорировать это MainAppLogic
не сервер в стойку, а просто разместить запрос localhost:8080
потому что там сервер запустился?
2 ответа
Первое: зачем настраивать класс для запуска приложения? Вы можете использовать rackup
инструмент, который является стандартом де-факто для запуска приложений Rack. Еще некоторые подробности об этом здесь.
Код вашего приложения становится:
class App
def call(env)
return [200, {}, ['Hello, World!']]
end
end
и с config.ru
require_relative 'app'
run App.new
вы можете запустить приложение, запустив rackup
в каталоге вашего проекта.
Что касается ошибки, сообщение довольно ясно. rack-test
ожидает, что возвращаемое значение app
Метод будет экземпляром приложения стойки (объект, который отвечает на call
метод). Посмотрите, что происходит в rack-test
внутренности (за ними довольно легко следовать, как совет - сфокусируйтесь на них в заданном порядке: lib/rack/test/methods.rb#L30
lib/rack/mock_session.rb#L7
lib/rack/test.rb#L244
lib/rack/mock_session.rb#L30
, Обратите внимание, как Rack::MockSession
как это используется при обработке запросов (например, когда вы звоните get
метод в ваших тестах) и, наконец, как call
метод в вашем приложении выполняется.
Я надеюсь, что теперь понятно, почему тест должен выглядеть примерно так (да, вам не нужно иметь сервер, работающий при выполнении ваших тестов):
describe App do
def app
App.new
end
it "does a triple backflip" do
get "/"
expect(last_response.body).to eq("Hello, World")
end
end
PS Извините за форму ссылок на rack-test
, не могу добавить больше 2 с моими текущими баллами:P
Ваше приложение должно быть именем класса, например вместо:
def app
MainAppLogic.new
end
Вы должны использовать
def app
MainAppLogic
end
Вам не нужно указывать порт для выполнения get
потому что приложение стойки запускается в контексте тестов; так что это должно быть правильно:
it "starts a server when initialized" do
get "/"
last_response.body.should be != nil
end
Также в качестве рекомендации предпочитаю использовать новый expect
формат вместо should
см. http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
И ваш MainAppLogic
, должно быть что-то вроде:
class MainAppLogic < Sinatra::Base
get '/' do
'Hello world'
end
end