2013-02-21 11 views
8

Mam metody POST, która akceptuje JSON:Jak przetestować moje JSON API z 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 

Jako początkujących do rspec jestem zdezorientowany próbuje dowiedzieć się, jak napisać test na tym stanowisku z akceptowalnym ładunkiem JSON. Najbliższe jest to, co jest fatalnie niedokładne, ale wydaje mi się, że nie pytam boga Google o właściwe pytania, które mogłyby mi pomóc.

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 

Wszelkie wskazówki dotyczące najlepszych praktyk dotyczące testowania interfejsów API w aplikacji Sinatra również będą najbardziej doceniane.

+0

Widziałaś to? http://stackoverflow.com/questions/5159882/how-to-check-for-a-json-response-using-rspec/5161898#5161898 – zetetic

Odpowiedz

9

Kod, którego użyłeś, jest w porządku, chociaż ułożyłbym go nieco inaczej, ponieważ nie lubię używać it blokuje to, co normalnie widzisz, myślę, że to zachęca do testowania więcej niż jednego aspektu systemu naraz:

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

używałem let bo to lepsze niż zmiennej instancji w before bloku (sława do Ciebie nie robi tego). Numer post znajduje się w bloku before, ponieważ nie jest częścią specyfikacji, ale efektem ubocznym, który występuje przed tym, co wyszukujesz. subject jest odpowiedzią i sprawia, że ​​it jest prostym połączeniem.

Ponieważ sprawdzanie odpowiedź jest ok, jest potrzebny tak często umieścić go w shared example:

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

a następnie wywołać go jako takie:

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

a ponieważ typ zawartość zmienia się tak często , Umieściłem to w pomocniku:

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 

Łatwo dodać to tam, gdzie jest to potrzebne poprzez włączenie go poprzez config RSpec:

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

następnie:

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

Powiedziawszy to wszystko, osobiście, nie będę pisać za pomocą JSON. HTTP POST jest prosty w obsłudze, a każda forma i biblioteka javascript to łatwo i dobrze. Odpowiadaj na JSON, ale nie wysyłaj JSON, HTTP jest o wiele łatwiejsze.


Edycja: po zapisaniu się na Helpers trochę powyżej zdałem sobie sprawę it would be more helpful as a gem.

Powiązane problemy