2012-07-11 16 views
9

मैं JSON प्रारूप और वर्सन (: http://railscasts.com/episodes/350-rest-api-versioning इस उत्कृष्ट रयान के कलाकारों के अनुसार) में एक REST API होने एक रेल आवेदन पर काम कर रहा हूँ अंदर कुछ हैडर अनुरोधों जोड़ें।Rspec: रूटिंग चश्मा

उदाहरण के लिए, वहाँ एक युक्ति/अनुरोध कल्पना है:

require 'spec_helper' 

describe "My Friends" do 
    describe "GET /my/friends.json" do 
    it "should get my_friends_path" do 
     get v1_my_friends_path, {}, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'} 
     response.status.should be(401) 
    end 
    end 
end 

और यह अच्छी तरह से काम करता है। लेकिन (इस उदाहरण को रखते हुए) हम रूटिंग स्पेक कैसे लिख सकते हैं? मिसाल के तौर पर इस कल्पना सही नहीं है:

require 'spec_helper' 

describe "friends routing" do 
    it "routes to #index" do 
    get("/my/friends.json", nil, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'}). 
     should route_to({ action: "index", 
        controller: "api/v1/private/my/friends", 
         format: "json" }) 
    end 
end 

मैं (जैसे request.headers['Accept'] और @request.headers['Accept'], जहां request अपरिभाषित है और @request नहीं के बराबर है) के रूप में अलग अलग तरीकों की कोशिश की, मैं वास्तव में नहीं देखता कि कैसे करना है।

मैं रूबी 1.9.3 पर हूँ, 3.2.6 और rspec-रेल 2.11.0 रेल। धन्यवाद।

उत्तर

5

वर्तमान में आप रूटिंग चश्मा में addititional हेडर नहीं भेज सकते हैं, इस actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb में line 608 की वजह से है, जहां यह कहते हैं:

env = Rack::MockRequest.env_for(path, {:method => method}) 

path आपके अनुरोध पथ "/my/friends.json" है और विधि :get जिसके परिणामस्वरूप env कुछ होता है निम्न की तरह:

{ 
"rack.version"=>[1, 1], 
"rack.input"=>#<StringIO:0xb908f5c>, 
"rack.errors"=>#<StringIO:0xb908fac>, 
"rack.multithread"=>true, 
"rack.multiprocess"=>true, 
"rack.run_once"=>false, 
"REQUEST_METHOD"=>"GET", 
"SERVER_NAME"=>"your-url.com", # if path was http://your-url.com/ 
"SERVER_PORT"=>"80", 
"QUERY_STRING"=>"", 
"PATH_INFO"=>"/", 
"rack.url_scheme"=>"http", 
"HTTPS"=>"off", 
"SCRIPT_NAME"=>"", 
"CONTENT_LENGTH"=>"0" 
} 

यदि आपपर नकल करने में सक्षम हैं 10 env_for द्वारा उत्पन्न किए गए लोगों की तुलना में अन्य शीर्षकों को इंजेक्ट करना संभव होना चाहिए (उपरोक्त हैश देखें)।

आप वर्तमान में route_to मिलान गलत उपयोग कर रहे हैं उसके अलावा, आप जहां विधि और इस तरह पथ निर्दिष्ट एक हैश पर बुलाना चाहिए:

{ get: '/' }.should route_to(controller: 'main', action: 'index') 

हमें बताएं कि क्या आपका उपहास करने में सक्षम थे चलो बाहर env_for और इसे अपने शीर्षलेख वापस करने दें, यह जानना अच्छा लगेगा।

सादर क्रिस्टोफ

+0

आप "जमे हुए हैश को संशोधित नहीं कर सकते" त्रुटि कैसे प्राप्त कर चुके हैं? –

+0

मैं शायद आरएसपीईसी या रूबी के पुराने संस्करण का उपयोग कर रहा था, जहां हैश जमे हुए नहीं थे। –

5
before do 
    ActionDispatch::TestRequest::DEFAULT_ENV["action_dispatch.request.accepts"] = "application/vnd.application-v1+json" 
end 

after do 
    ActionDispatch::TestRequest::DEFAULT_ENV.delete("action_dispatch.request.accepts") 
end 
+0

आप "जमे हुए हैश को संशोधित नहीं कर सकते" त्रुटि को कैसे प्राप्त किया? –

13

क्रिस्टोफ के और पिओट्र के जवाब से विचारों के संयोजन से, मैं एक समाधान है कि मेरे लिए काम किया के साथ आया था। मैं rspec और रेल 3.0 का उपयोग कर रहा हूँ।

it 'should route like i want it to' do 
    Rack::MockRequest::DEFAULT_ENV["HTTP_ACCEPT"] = "*/*" 
    {get: "/foo/bar"}. 
    should route_to(
    controller: 'foo', 
    action: 'bar', 
) 
    Rack::MockRequest::DEFAULT_ENV.delete "HTTP_ACCEPT" 
end 
+0

आप "जमे हुए हैश को संशोधित नहीं कर सकते" त्रुटि कैसे प्राप्त कर चुके हैं? –

+0

@ChrisHough हम्म, मुझे यह त्रुटि याद नहीं है। लेकिन ध्यान दें कि यह समाधान रेल के लिए था 3. आप शायद 4.x पर हैं और हो सकता है कि वे तब से DEFAULT_ENV हैश को ठंडा करना शुरू कर दें ... –

+0

हाँ, मुझे अनुरोध चश्मा के लिए अपने रूटिंग चश्मे को हटाना पड़ा। जो मेरे द्वारा पूरी तरह से ठीक है। –

2

आप Rack::MockRequest.env_for विधि उपहास करने के लिए rspec के and_wrap_original का उपयोग कर सकते हैं:

expect(Rack::MockRequest).to receive(:env_for).and_wrap_original do |original_method, *args, &block| 
    original_method.call(*args, &block).tap { |hash| hash['HTTP_ACCEPT'] = 'application/vnd.myapp+json; level=1' } 
end 
+1

यह समाधान रेल के लिए मेरे लिए काम करता है 5 – justNeph

+1

@justNeph क्या आप इस पर विस्तार कर सकते हैं कि आपने इसे कैसे कार्यान्वित किया है या आपका स्पेक कैसा दिखता है? –

+0

आप "जमे हुए हैश को संशोधित नहीं कर सकते" त्रुटि कैसे प्राप्त कर चुके हैं? –

0

रेल 3 और 4 मैं किया था एक RSpec around hook में निम्नलिखित:

around do |example| 
    Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1' 

    example.run 

    Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT' 
end 

Rack >= 2.0.3 के बाद से (used by Rails 5) Rack::MockRequest::DEFAULT_ENVhash is frozen

आप लगातार फिर से परिभाषित कर सकते हैं और Kernel.silence_warnings का उपयोग रूबी चेतावनी मौन करने:

around do |example| 
    silence_warnings do 
    Rack::MockRequest::DEFAULT_ENV = Rack::MockRequest::DEFAULT_ENV.dup 
    end 

    Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1' 

    example.run 

    Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT' 
end 

यह हैक का एक सा है, लेकिन यह एक आकर्षण की तरह काम करता है।