2013-02-21 24 views
8

我有接受JSON POST方法:如何測試我的JSON API與西納特拉+ rspec的

post '/channel/create' do 
    content_type :json 

    @data = JSON.parse(env['rack.input'].gets) 

    if @data.nil? or [email protected]_key?('api_key') 
    status 400 
    body({ :error => "JSON corrupt" }.to_json) 
    else 
    status 200 
    body({ :error => "Channel created" }.to_json) 
    end 

作爲一個新手到RSPEC我感到困惑試圖找出如何寫一個測試針對POST具有可接受的JSON負載。我最接近的是這種可悲的不準確,但我似乎並沒有向谷歌神提出正確的問題來幫助我。

it "accepts create channel" do 
    h = {'Content-Type' => 'application/json'} 
    body = { :key => "abcdef" }.to_json 
    post '/channel/create', body, h 
    last_response.should be_ok 
    end 

在Sinatra測試API的任何最佳實踐指南都將得到最多讚賞。

+0

你看到這一個? http://stackoverflow.com/questions/5159882/how-to-check-for-a-json-response-using-rspec/5161898#5161898 – zetetic 2013-02-21 20:09:12

回答

9

您使用的代碼很好,但我的結構略有不同,因爲我不喜歡按照通常看到的方式使用it塊,我認爲它鼓勵測試系統的多個方面在一個時間:

let(:body) { { :key => "abcdef" }.to_json } 
before do 
    post '/channel/create', body, {'CONTENT_TYPE' => 'application/json'} 
end 
subject { last_response } 
it { should be_ok } 

我用let因爲它比一個實例變量的before塊更好的(榮譽給你不這樣做)。 post位於before區塊中,因爲它不是規範的一部分,但是在您指定的內容之前會出現副作用。 subject是迴應,並使it一個簡單的電話。

因爲檢查響應是確定的,需要經常我把它放在一個​​:

shared_examples_for "Any route" do 
    subject { last_response } 
    it { should be_ok } 
end 

,然後調用它是這樣:

describe "Creating a new channel" do 
    let(:body) { { :key => "abcdef" }.to_json } 
    before do 
    post '/channel/create', body, {'CONTENT_TYPE' => 'application/json'} 
    end 
    it_should_behave_like "Any route" 
    # now spec some other, more complicated stuff… 
    subject { JSON.parse(last_response.body) } 
    it { should == "" } 

而且由於內容類型,以便經常變化,我把它放在幫手裏:

module Helpers 

    def env(*methods) 
     methods.each_with_object({}) do |meth, obj| 
     obj.merge! __send__(meth) 
     end 
    end 

    def accepts_html 
     {"HTTP_ACCEPT" => "text/html" } 
    end 

    def accepts_json 
     {"HTTP_ACCEPT" => "application/json" } 
    end 

    def via_xhr  
     {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"} 
    end 

很容易在需要的地方添加它通過將其包括通過RSpec的配置:

RSpec.configure do |config| 
    config.include Helpers, :type => :request 

則:

describe "Creating a new channel", :type => :request do 
    let(:body) { { :key => "abcdef" }.to_json } 
    before do 
    post '/channel/create', body, env(:accepts_json) 
    end 

說了這麼多,就個人而言,我不會發布使用JSON。 HTTP POST很容易處理,並且每個表單和JavaScript庫都可以輕鬆完成。盡一切辦法迴應JSON,但不要發佈JSON,HTTP要容易得多。


編輯:寫出Helpers位之上,我意識到it would be more helpful as a gem後。