0

这是我的机架应用程序:

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”。我无法说服 rack-test 使用它。这是我的测试:

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,因为那里的服务器已经启动?

4

2 回答 2

1

第一件事:为什么要运行应用程序的自定义类?您可以使用该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

于 2016-08-19T22:27:20.477 回答
0

您的应用程序应该是类名,例如,而不是:

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
于 2016-08-18T13:58:59.763 回答