2013-02-21 14 views
8

Tôi có một phương pháp bài chấp nhận JSON:Làm thế nào để kiểm tra API JSON của tôi với 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 

Là một newbie để RSpec Tôi đang hoang mang cố gắng tìm hiểu làm thế nào để viết một bài kiểm tra chống lại POST với tải trọng JSON chấp nhận được. Gần nhất tôi đã nhận được là điều này là woefully không chính xác nhưng tôi dường như không được yêu cầu Google thần các câu hỏi đúng để giúp tôi ra ở đây.

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 

Mọi hướng dẫn thực hành tốt nhất để thử nghiệm API ở Sinatra cũng sẽ được đánh giá cao nhất.

+0

Anh có thấy cái này? http://stackoverflow.com/questions/5159882/how-to-check-for-a-json-response-using-rspec/5161898#5161898 – zetetic

Trả lời

9

Mã bạn đã sử dụng là tốt, mặc dù tôi sẽ cấu trúc hơi khác một chút vì tôi không muốn sử dụng it chặn theo cách bạn thường thấy, tôi khuyến khích thử nghiệm nhiều khía cạnh của một hệ thống tại một thời điểm:

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

tôi đã sử dụng let vì nó là tốt hơn so với một biến Ví dụ trong một khối before (thanh danh cho bạn vì đã không làm điều đó). Các post là trong một khối before bởi vì nó không thực sự là một phần của spec, nhưng một tác dụng phụ xảy ra trước khi những gì bạn đang speccing. Các subject là phản ứng và làm cho it một cuộc gọi đơn giản.

Bởi vì kiểm tra phản ứng là ok là cần thiết vì vậy thường xuyên Tôi đặt nó trong một shared example:

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

và sau đó gọi nó như vậy:

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

và vì kiểu nội dung thay đổi thường xuyên , Tôi đặt nó trong một người trợ giúp:

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 

Thật dễ dàng để thêm vào nơi cần thiết bằng cách bao gồm nó thông qua cấu hình RSpec:

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

thì:

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

Có nói tất cả những gì, cá nhân, tôi sẽ không gửi sử dụng JSON. HTTP POST rất đơn giản để xử lý và mọi thư viện biểu mẫu và javascript đều dễ dàng và tốt. Trả lời bằng JSON bằng mọi cách, nhưng không đăng JSON, HTTP dễ dàng hơn rất nhiều.


Chỉnh sửa: sau khi viết ra Helpers bit ở trên, tôi nhận ra it would be more helpful as a gem.

0

Hình như khả năng làm post :update, '{"some": "json"}' đã được thêm vào test_case.rb ActionPack nội bộ được sử dụng bởi rspec trong cam kết này: https://github.com/rails/rails/commit/5b9708840f4cc1d5414c64be43c5fc6b51d4ecbf

Vì bạn đang sử dụng Sinatra Tôi không chắc chắn cách tốt nhất để có được những thay đổi — bạn có thể nâng cấp ActionPack trực tiếp hoặc vá từ cam kết trên.