我写了一些Rack-Middleware,现在我正试图用Rspec测试它。但所有Rack-Middleware都使用'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
答案 0 :(得分:24)
你只需要世界上最简单的Rack应用程序:
let(:app) { lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['OK']]} }
此外,您的中间件的构造函数应该接收一个应用程序作为其第一个参数而不是哈希值,因此它应该读取:
subject { MyMiddleWare.new(app) }
尽管如此,您的测试很可能需要确定中间件对请求的影响。因此,您可能会编写一个稍微复杂的机架应用来窥探您的中间件。
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
答案 1 :(得分:0)
我相信您应该使用模拟http请求的请求规范(您的中间件应该包含在rails中间件堆栈中)。有关rspec请求规范here的详细信息,请参阅。
UPD 我想我已经找到了你需要的东西,使用Test :: Unit,但很容易为RSpec重写:rack-ssl-enforcer
答案 2 :(得分:0)
我这样测试了我的
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