8

JSONを受け入れるpostメソッドがあります:

post '/channel/create' do
  content_type :json

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

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

rspecの初心者として、許容可能なJSONペイロードを使用してそのPOSTに対するテストを作成する方法を理解しようとすると戸惑います。私が最も近づいたのはこれですが、これはひどく不正確ですが、ここで私を助けるために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をテストするためのベストプラクティスのガイダンスも最も高く評価されます。

4

3 に答える 3

12

使用したコードは問題ありませんが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上記のビットを書き留めた後、私はそれが宝石としてより役立つだろうことに気づきました。

于 2013-02-23T06:37:20.590 に答える
0

last_response を JSON として見たい場合は、rack-test-json を試すことができます。

expect(last_response).to be_json
expect(last_response.as_json['key']).to be == 'value'
于 2016-07-12T02:41:58.000 に答える
0

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

Sinatra を使用しているため、これらの変更を取得する最善の方法がわかりません。ActionPack を直接アップグレードするか、上記のコミットからパッチを適用できる可能性があります。

于 2014-02-13T16:39:49.220 に答える