2013-02-21 8 views
8

ich einen Beitrag Methode, die JSON akzeptiert:Wie teste ich meine JSON API mit Sinatra + 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 

Als Neuling auf RSpec ich, um herauszufinden, bin verwirrt versucht, wie ein Test gegen diesen Beitrag zu schreiben mit einer akzeptablen JSON-Nutzlast. Am nächsten kommt mir das, was sehr ungenau ist, aber ich möchte den Google-Gott nicht die richtigen Fragen stellen, um mir hier zu helfen.

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 

Jede Best Practice Anleitung zum Testen von APIs in Sinatra wird ebenfalls sehr geschätzt.

+0

Haben Sie den? http://stackoverflow.com/questions/5159882/how-to-check-for-a-json-response-using-rspec/5161898#5161898 – zetetic

Antwort

9

Der Code, den Sie verwendet haben, ist in Ordnung, obwohl ich es etwas anders strukturieren würde, da ich it Blöcke nicht so verwenden möchte, wie Sie sie normalerweise sehen, ich denke es ermutigt Tests von mehr als einem Aspekt eines Systems zu einem Zeitpunkt:

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

ich let verwendet habe, weil es besser ist, als eine Instanzvariable in einem before Block (großes Lob an Sie nicht zu tun, dass). Die post ist in einem before Block, weil es nicht wirklich Teil der Spezifikation ist, aber ein Nebeneffekt, der vor dem auftritt, was Sie speccing sind. Die subject ist die Antwort und das macht die it einen einfachen Anruf.

Da die Antwort Überprüfung ok ist so häufig benötigt wird, ich habe es in einem shared example:

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

und dann rufen als solche:

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 == "" } 

und weil der Typ Inhalt ändert sich so oft Ich habe das in einen Helfer eingefügt:

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 

Es ist einfach, das hinzuzufügen, wo es gebraucht wird indem sie sie über die RSpec Config einschließlich:

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

dann:

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

Nachdem alles gesagt, dass, persönlich, würde ich nicht schreiben JSON verwenden. HTTP POST ist einfach zu handhaben, und jede Form und Javascript Bibliothek macht es einfach und gut. Reagieren Sie mit JSON auf alle Fälle, aber schreiben Sie JSON nicht, HTTP ist viel einfacher.


Edit: nach dem Helpers Bit auszuschreiben oben I it would be more helpful as a gem realisiert.

Verwandte Themen