2013-02-21 14 views
8

RSpecのシナトラ+と私のJSONのAPIをテストするにはどうすればよい:私はそのPOSTに対してテストを作成する方法を把握しようと戸惑っていますRSpecのために初心者として私はJSON受け入れるpostメソッド持って

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 

を受け入れ可能なJSONペイロードで私が得た最も近いものは悲観的に不正確ですが、私はGoogleの神にここで私を助ける正しい質問をしているようには思えません。

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

答えて

9

itブロックを通常の方法でブロックするのが好きではないので、私は少し違った構成にしていますが、使用したコードは問題ありません。システムの複数の側面のテストが奨励されると思います時:それは(それをやっていないため、あなたに称賛)beforeブロック内のインスタンス変数よりはましだから

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を使用しました。 postbeforeブロックに含まれています。これは実際には仕様の一部ではありませんが、あなたの仕様に先立って発生する副作用です。 subjectは応答であり、itは簡単な呼び出しになります。

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

をして、そのように呼び出します:応答をチェックすることokですので

ので、多くの場合、私は​​にそれを置く必要がある

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.configure do |config| 
    config.include Helpers, :type => :request 

その後:RSpecのコンフィグを経由して、それを含めることによって、

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を実現。

0

post :update, '{"some": "json"}'を行う能力がコミットこの中でRSpecのが使用する内部ActionPackのtest_case.rbに追加されたように見える: https://github.com/rails/rails/commit/5b9708840f4cc1d5414c64be43c5fc6b51d4ecbf

あなたはシナトラを使っているので、私はわからないんだけど、それらを取得するための最良の方法変更 - ActionPackを直接アップグレードすることも、上記のコミットからパッチを当てることもできます。

0

あなたはJSONとしてlast_responseを見たい場合は、あなたがrack-test-json which makes this trivialを試みることができる:

expect(last_response).to be_json 
expect(last_response.as_json['key']).to be == 'value' 
関連する問題