Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 用Rspec测试中间件_Ruby On Rails_Rspec_Rack_Rack Middleware - Fatal编程技术网

Ruby on rails 用Rspec测试中间件

Ruby on rails 用Rspec测试中间件,ruby-on-rails,rspec,rack,rack-middleware,Ruby On Rails,Rspec,Rack,Rack Middleware,我已经编写了一些机架中间件,现在我正试图用Rspec对其进行测试。但是,所有机架中间件都用一个“app”参数实例化,该参数表示Rails应用程序本身。你们怎么在Rspec里模拟这个 比如说, describe MyMiddleWare do let(:app) { # How do I mock a Rails app object here? } subject { MyMiddleWare.new(app: app) } it 'should blah blah

我已经编写了一些机架中间件,现在我正试图用Rspec对其进行测试。但是,所有机架中间件都用一个“app”参数实例化,该参数表示Rails应用程序本身。你们怎么在Rspec里模拟这个

比如说,

 describe MyMiddleWare do
    let(:app) { # How do I mock a Rails app object here? }
    subject { MyMiddleWare.new(app: app) }

    it 'should blah blah blah' do
       # a bunch of tests go here
    end
 end

我认为您应该使用模拟http请求的请求规范(您的中间件应该包含在rails中间件堆栈中)。请参阅rspec请求规范的更多详细信息

UPD我想我已经找到了您需要的东西,使用Test::Unit,但是为RSpec重写很容易:

我像这样测试了我的

describe Support::CharConverter do

  let(:env_hash) do
    {
      "HTTP_REFERER" => "", 
      "PATH_INFO" => "foo",
      "QUERY_STRING" => "bar",
      "REQUEST_PATH" => "is",
      "REQUEST_URI" => "here",
    }
  end

  subject do 
    Support::CharConverter.new(env_hash)
  end

  context 'sanitize_env' do

    it 'should keep key values the same if nothing to sanitize' do
      sanitized_hash = subject.sanitize_env(env_hash)
      # k = env_hash.keys[5]
      # v = env_hash.values[5]
      env_hash.each do |k, v|
        sanitized_hash[k].encoding.name.should eq("US-ASCII")
        sanitized_hash[k].should eq(v)
        sanitized_hash[k].valid_encoding?.should eq(true)
      end
    end
  end
end

您只需要世界上最简单的机架式应用程序:

let(:app) { lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['OK']]} }
此外,中间件的构造函数应接收一个应用程序作为其第一个参数,而不是散列,因此它应为:

subject { MyMiddleWare.new(app) }
不过,您的测试很可能需要确定中间件对请求的影响。因此,您可以编写一个稍微复杂一些的rack应用程序来监视您的中间件

class MockRackApp

  attr_reader :request_body

  def initialize
    @request_headers = {}
  end

  def call(env)
    @env = env
    @request_body = env['rack.input'].read
    [200, {'Content-Type' => 'text/plain'}, ['OK']]
  end

  def [](key)
    @env[key]
  end

end
然后您可能需要使用Rack::MockRequest来实际发送请求。比如:

describe MyMiddleWare do

  let(:app) { MockRackApp.new }
  subject { described_class.new(app) }

  context "when called with a POST request" do
    let(:request) { Rack::MockRequest.new(subject) }
    before(:each) do
      request.post("/some/path", input: post_data, 'CONTENT_TYPE' => 'text/plain')
    end

    context "with some particular data" do
      let(:post_data) { "String or IO post data" }

      it "passes the request through unchanged" do
        expect(app['CONTENT_TYPE']).to eq('text/plain')
        expect(app['CONTENT_LENGTH'].to_i).to eq(post_data.length)
        expect(app.request_body).to eq(post_data)
      end
    end
  end
end

这里没有主题调用,这实际上是如何工作的?这实际上不是一个有效的机架应用程序。
lambda
必须采用一个参数才能成为有效的Rack应用程序。简单代码示例中的固定算术-谢谢@branch14。