Настройка 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#L30lib/rack/mock_session.rb#L7lib/rack/test.rb#L244lib/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
Другие вопросы по тегам