2012-03-06 17 views
54

मैंने वेब को खराब कर दिया है, लेकिन, हां, मुझे बस सामग्री प्रकार को सही तरीके से भेजने के लिए रुपेक नहीं मिल रहा है, इसलिए मैं अपने JSON API का परीक्षण कर सकता हूं। मैं टेम्पलेट्स, रेल 3.0.11, और रूबी 1.9.2-पी 180 के लिए आरएबीएल मणि का उपयोग कर रहा हूं।रुपयेपेक का उपयोग करके, मैं रेल नियंत्रक 3.0.11 में अपने नियंत्रक के JSON प्रारूप का परीक्षण कैसे करूं?

मेरे कर्ल उत्पादन है, जो ठीक काम करता है (एक 401 होना चाहिए, मुझे पता है):

mrsnuggles:tmp gaahrdner$ curl -i -H "Accept: application/json" -X POST -d @bleh http://localhost:3000/applications 
HTTP/1.1 403 Forbidden 
Content-Type: application/json; charset=utf-8 
Cache-Control: no-cache 
X-Ua-Compatible: IE=Edge 
X-Runtime: 0.561638 
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-02-18) 
Date: Tue, 06 Mar 2012 01:10:51 GMT 
Content-Length: 74 
Connection: Keep-Alive 
Set-Cookie: _session_id=8e8b73b5a6e5c95447aab13dafd59993; path=/; HttpOnly 

{"status":"error","message":"You are not authorized to access this page."} 

नमूना अपने परीक्षण मामलों में से एक से:

describe ApplicationsController do 
    render_views 
    disconnect_sunspot 

    let(:application) { Factory.create(:application) } 

    subject { application } 

    context "JSON" do 

    describe "creating a new application" do 

     context "when not authorized" do 
     before do 
      json = { :application => { :name => "foo", :description => "bar" } } 
      request.env['CONTENT_TYPE'] = 'application/json' 
      request.env['RAW_POST_DATA'] = json 
      post :create 
     end 

     it "should not allow creation of an application" do 
      Application.count.should == 0 
     end 

     it "should respond with a 403" do 
      response.status.should eq(403) 
     end 

     it "should have a status and message key in the hash" do 
      JSON.parse(response.body)["status"] == "error" 
      JSON.parse(response.body)["message"] =~ /authorized/ 
     end 
     end 

     context "authorized" do 
     end 
    end 
    end 
end 

इन परीक्षणों हालांकि पारित कभी नहीं, मैं हमेशा रीडायरेक्ट हो जाते हैं और मेरी सामग्री-प्रकार हमेशा text/html है, भले ही मैं अपने पहले ब्लॉक में टाइप कैसे निर्दिष्ट करता हूं:

# nope 
before do 
    post :create, {}, { :format => :json } 
end 

# nada 
before do 
    post :create, :format => Mime::JSON 
end 

# nuh uh 
before do 
    request.env['ACCEPT'] = 'application/json' 
    post :create, { :foo => :bar } 
end 

यहाँ rspec उत्पादन होता है:

Failures: 

    1) ApplicationsController JSON creating a new application when not authorized should respond with a 403 
    Failure/Error: response.status.should eq(403) 

     expected 403 
      got 302 

     (compared using ==) 
    # ./spec/controllers/applications_controller_spec.rb:31:in `block (5 levels) in <top (required)>' 

    2) ApplicationsController JSON creating a new application when not authorized should have a status and message key in the hash 
    Failure/Error: JSON.parse(response.body)["status"] == "errors" 
    JSON::ParserError: 
     756: unexpected token at '<html><body>You are being <a href="http://test.host/">redirected</a>.</body></html>' 
    # ./spec/controllers/applications_controller_spec.rb:35:in `block (5 levels) in <top (required)>' 

आप मैं, HTML स्वरूप के लिए 302 रीडायरेक्ट हो रही है, भले ही मैं 'आवेदन/json' निर्दिष्ट करने के लिए कोशिश कर रहा हूँ देख सकते हैं।

यहाँ मेरी application_controller.rb है, rescue_from बिट के साथ:

class ApplicationController < ActionController::Base 

rescue_from ActiveRecord::RecordNotFound, :with => :not_found 

    protect_from_forgery 
    helper_method :current_user 
    helper_method :remove_dns_record 

rescue_from CanCan::AccessDenied do |exception| 
    flash[:alert] = exception.message 
    respond_to do |format| 
     h = { :status => "error", :message => exception.message } 
     format.html { redirect_to root_url } 
     format.json { render :json => h, :status => :forbidden } 
     format.xml { render :xml => h, :status => :forbidden } 
    end 
    end 

    private 

    def not_found(exception) 
    respond_to do |format| 
     h = { :status => "error", :message => exception.message } 
     format.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => :not_found } 
     format.json { render :json => h, :status => :not_found } 
     format.xml { render :xml => h, :status => :not_found } 
    end 
    end 
end 

और यह भी applications_controller.rb, विशेष रूप से 'बनाने' कार्रवाई है जो कि मैं क्या परीक्षण करने के लिए कोशिश कर रहा हूँ। इस समय यह काफी बदसूरत है क्योंकि मैं state_machine का उपयोग कर रहा हूं और हटाई गई विधि को ओवरराइड कर रहा हूं।

def create 
    # this needs to be cleaned up and use accepts_attributes_for 
    @application = Application.new(params[:application]) 
    @environments = params[:application][:environment_ids] 
    @application.environment_ids<<@environments unless @environments.blank? 

    if params[:site_bindings] == "new" 
     @site = Site.new(:name => params[:application][:name]) 
     @environments.each do |e| 
     @site.siteenvs << Siteenv.new(:environment_id => e) 
     end 
    end 

    if @site 
     @application.sites << @site 
    end 

    if @application.save 
     if @site 
     @site.siteenvs.each do |se| 
      appenv = @application.appenvs.select {|e| e.environment_id == se.environment_id } 
      se.appenv = appenv.first 
      se.save 
     end 
     end 
     flash[:success] = "New application created." 
     respond_with(@application, :location => @application) 
    else 
     render 'new' 
    end 

    # super stinky :(
    @application.change_servers_on_appenvs(params[:servers]) unless params[:servers].blank? 
    @application.save 
    end 

मैं स्रोत कोड यहाँ देखा है: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb, और यह इसे सही ढंग से है कि इसी तरह के मुद्दों और संभावित समाधानों है लगता ढेर अतिप्रवाह पर सवालों की एक संख्या के रूप में जवाब देना चाहिए, साथ ही लगता है, लेकिन कोई भी काम मेरे लिए।

मैं क्या गलत कर रहा हूं?

उत्तर

56

अनुरोध के पैरामीटर हैश अंदर :format कुंजी चलती है, इस तरह का प्रयास करें:

describe ApplicationsController do 
    render_views 
    disconnect_sunspot 

    let(:application) { Factory.create(:application) } 

    subject { application } 

    context "JSON" do 

    describe "creating a new application" do 

     context "when not authorized" do 
     it "should not allow creation of an application" do 
      params = { :format => 'json', :application => { :name => "foo", :description => "bar" } } 
      post :create, params 
      Expect(Application.count).to eq(0) 
      expect(response.status).to eq(403) 
      expect(JSON.parse(response.body)["status"]).to eq("error") 
      expect(JSON.parse(response.body)["message"]).to match(/authorized/) 
     end 


     end 

     context "authorized" do 
     end 
    end 
    end 
end 

मुझे पता है कि यह कैसे जाता है! जिस तरह से मैंने अपना परीक्षण निर्धारित किया है, और वे ठीक काम कर रहे हैं!

+0

मेरे पास आर्थर वापस आने के लिए धन्यवाद। मैंने आपके द्वारा किए गए परिवर्तन किए हैं, लेकिन मुझे अभी भी वही परिणाम मिल रहे हैं, जहां परीक्षण को HTML '1 पर रीडायरेक्ट किया जा रहा है) अनुप्रयोग नियंत्रक JSON एक नया एप्लिकेशन बनाते समय अधिकृत नहीं होने पर किसी अनुप्रयोग के निर्माण की अनुमति नहीं देनी चाहिए ' ' विफलता/त्रुटि: JSON.parse (response.body) ["status"] == "त्रुटियां" ' ' JSON :: पार्सर त्रुटि: ' ' 756: अप्रत्याशित टोकन ' पर आप redirected हैं। '' ' # ./spec/controllers/applications_controller_spec।आरबी: 25: ब्लॉक (5 स्तर) में <शीर्ष (आवश्यक)> ' – gaahrdner

+0

में बस आपके नियंत्रक कोड की समीक्षा की गई थी! और मैंने थोड़ा सा परीक्षण बदल दिया! कोशिश करके देखो! –

+0

दुर्भाग्य से यह या तो काम नहीं करेगा, http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html#method-i-post के अनुसार। 'सामग्री-प्रकार 'या' स्वीकार करें 'हेडर निर्दिष्ट किए बिना, रेल केवल' टेक्स्ट/html' पर डिफ़ॉल्ट हो जाएंगे। इस कर्ल कथन के समान: 'curl -i -X ​​POST-d '{: application => {: name =>" foo ",: description =>" bar "}}' http: // localhost: 3000/application' – gaahrdner

61

मुझे एहसास है कि :format => :json सेटिंग एक समाधान है (जैसा ऊपर बताया गया है)। हालांकि, मैं उन शर्तों का परीक्षण करना चाहता था जो मेरे एपीआई के क्लाइंट का उपयोग करेंगे। मेरे ग्राहक :format पैरामीटर सेट नहीं करेंगे, इसके बजाय वे Accept HTTP शीर्षलेख सेट करेंगे। यदि आप इस समाधान में रूचि रखते हैं, तो मैंने यहां उपयोग किया है:

# api/v1/test_controller_spec.rb 
require 'spec_helper.rb' 
describe Api::V1::TestController do 
    render_views 
    context "when request sets accept => application/json" do 
    it "should return successful response" do 
     request.accept = "application/json" 
     get :test 
     response.should be_success 
    end 
    end 
end 
+6

बस 'request.accept = "application/json" को जोड़कर मेरी समस्या हल हो गई। यह सबसे सरल समाधान की तरह लगता है। धन्यवाद! – user3233065

+0

रेल 4 और रुपेक 3.2.1 इस मुद्दे को हल किया गया –

+0

रेल 4 और रुपे 3.3 साथ ही –

संबंधित मुद्दे