2013-07-06 7 views
14

Я написал несколько промежуточных программ Rack-Middleware, и теперь я пытаюсь проверить его с помощью Rspec. Но все Rack-Middleware создаются с аргументом «app», который представляет собой приложение Rails. Как вы, ребята, издеваетесь над этим в Rspec?Тестирование промежуточного программного обеспечения с 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 

ответ

18

You просто нужно простейшее в мире приложение для монтажа в стойку:

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

Кроме того, конструктор вашего Middleware должен получить приложение в качестве первого параме тер не хэш, так что следует читать:

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

Здесь нет ни одного вопроса, как это работает? – Calin

+0

Это действительно недействительное приложение Rack. 'Lambda' должен был бы принять аргумент как действительное приложение Rack. – branch14

+0

Обновлено для публикации на тему - спасибо, @Calin. – Ritchie

0

Я считаю, что вы должны использовать запрос спецификацию, имитирующий запрос HTTP (ваш промежуточный слой должен быть включен в рельсах стека промежуточного программное обеспечения). Более подробную информацию о спецификациях запроса rspec here.

UPD Я думаю, что я нашел именно то, что вам нужно, с Test :: Unit, но это легко переписать для RSpec: rack-ssl-enforcer

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 
Смежные вопросы

 Смежные вопросы