2013-07-06 25 views
14

Tôi đã viết một số Rack-Middleware và bây giờ tôi đang cố gắng thử nghiệm nó với Rspec. Nhưng tất cả Rack-Middleware được khởi tạo với một đối số 'app', đại diện cho chính ứng dụng Rails. Làm thế nào để các bạn giả lập điều này trong Rspec?Thử nghiệm Middleware với Rspec

Ví dụ,

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 

Trả lời

18

Bạn chỉ cần ứng dụng Giá đơn giản nhất thế giới:

let(:app) { lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['OK']]} } 

Ngoài ra, trình xây dựng phần mềm trung gian của bạn sẽ nhận được ứng dụng làm trò chơi đầu tiên ter không phải là băm nên nó phải đọc:

Mặc dù vậy, thử nghiệm của bạn sẽ cần phải xác định tác dụng của phần mềm trung gian theo yêu cầu. Vì vậy, bạn có thể viết một ứng dụng giá tinh vi hơn một chút để theo dõi phần mềm trung gian của bạn.

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 

và sau đó bạn có thể muốn sử dụng Rack :: MockRequest để thực sự gửi yêu cầu. Một cái gì đó như:

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 
+0

Không có lời gọi nào để thực hiện ở đây, điều này thực sự hoạt động như thế nào? – Calin

+0

Đây thực sự không phải là ứng dụng Rack hợp lệ. 'Lambda' sẽ phải tranh luận là một ứng dụng Rack hợp lệ. – branch14

+0

Đã cập nhật để đăng lên chủ đề - cảm ơn, @Calin. – Ritchie

0

Tôi tin rằng bạn nên sử dụng yêu cầu thông số kỹ thuật mô phỏng một http request (middleware của bạn nên được đưa vào đường ray middleware stack). Xem thêm chi tiết về thông số yêu cầu rspec here.

UPD Tôi nghĩ rằng tôi đã tìm thấy chính xác những gì bạn cần, với Test :: Đơn vị, nhưng thật dễ dàng để viết lại cho RSpec: rack-ssl-enforcer

0

Tôi đã thử nghiệm của tôi như vậy

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