简体   繁体   English

使用Rspec,如何在Rails 3.0.11中测试我的控制器的JSON格式?

[英]Using Rspec, how do I test the JSON format of my controller in Rails 3.0.11?

I've scoured the web, but, alas, I just can't seem to get Rspec to correctly send content-type so I can test my JSON API. 我已经浏览了网页,但是,唉,我似乎无法让Rspec正确发送内容类型,所以我可以测试我的JSON API。 I'm using the RABL gem for templates, Rails 3.0.11, and Ruby 1.9.2-p180. 我正在使用RABL gem用于模板,Rails 3.0.11和Ruby 1.9.2-p180。

My curl output, which works fine (should be a 401, I know): 我的卷曲输出,工作正常(应该是401,我知道):

mrsnuggles:tmp gaahrdner$ curl -i -H "Accept: application/json" -X POST -d @bleh http://localhost:3000/applications
HTTP/1.1 403 Forbidden 
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
X-Ua-Compatible: IE=Edge
X-Runtime: 0.561638
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-02-18)
Date: Tue, 06 Mar 2012 01:10:51 GMT
Content-Length: 74
Connection: Keep-Alive
Set-Cookie: _session_id=8e8b73b5a6e5c95447aab13dafd59993; path=/; HttpOnly

{"status":"error","message":"You are not authorized to access this page."}

Sample from one of my test cases: 我的一个测试用例中的示例:

describe ApplicationsController do
  render_views
  disconnect_sunspot

  let(:application) { Factory.create(:application) }

  subject { application }

  context "JSON" do

    describe "creating a new application" do

      context "when not authorized" do
        before do
          json = { :application => { :name => "foo", :description => "bar" } }
          request.env['CONTENT_TYPE'] = 'application/json'
          request.env['RAW_POST_DATA'] = json
          post :create
        end 

        it "should not allow creation of an application" do
          Application.count.should == 0
        end 

        it "should respond with a 403" do
          response.status.should eq(403)
        end 

        it "should have a status and message key in the hash" do
          JSON.parse(response.body)["status"] == "error"
          JSON.parse(response.body)["message"] =~ /authorized/
        end 
      end 

      context "authorized" do
      end 
    end
  end
end

These tests never pass though, I always get redirected and my content-type is always text/html , regardless of how I seem to specify the type in my before block: 这些测试从未通过,我总是被重定向,我的内容类型总是text/html ,无论我在前面的块中指定类型如何:

# nope
before do
  post :create, {}, { :format => :json }
end

# nada
before do
  post :create, :format => Mime::JSON
end

# nuh uh
before do
  request.env['ACCEPT'] = 'application/json'
  post :create, { :foo => :bar }
end

Here is the rspec output: 这是rspec输出:

Failures:

  1) ApplicationsController JSON creating a new application when not authorized should respond with a 403
     Failure/Error: response.status.should eq(403)

       expected 403
            got 302

       (compared using ==)
     # ./spec/controllers/applications_controller_spec.rb:31:in `block (5 levels) in <top (required)>'

  2) ApplicationsController JSON creating a new application when not authorized should have a status and message key in the hash
     Failure/Error: JSON.parse(response.body)["status"] == "errors"
     JSON::ParserError:
       756: unexpected token at '<html><body>You are being <a href="http://test.host/">redirected</a>.</body></html>'
     # ./spec/controllers/applications_controller_spec.rb:35:in `block (5 levels) in <top (required)>'

As you can see I'm getting the 302 redirect for the HTML format, even though I'm trying to specify 'application/json'. 正如您所看到的,我正在获取HTML格式的302重定向,即使我正在尝试指定'application / json'。

Here is my application_controller.rb , with the rescue_from bit: 这是我的application_controller.rb ,其中包含rescue_from位:

class ApplicationController < ActionController::Base

 rescue_from ActiveRecord::RecordNotFound, :with => :not_found

  protect_from_forgery
  helper_method :current_user
  helper_method :remove_dns_record

 rescue_from CanCan::AccessDenied do |exception|
    flash[:alert] = exception.message
    respond_to do |format|
      h = { :status => "error", :message => exception.message }
      format.html { redirect_to root_url }
      format.json { render :json => h, :status => :forbidden }
      format.xml  { render :xml => h, :status => :forbidden }
    end 
  end

  private

  def not_found(exception)
    respond_to do |format|
      h = { :status => "error", :message => exception.message }
      format.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => :not_found }
      format.json { render :json => h, :status => :not_found }
      format.xml  { render :xml => h, :status => :not_found }
    end
  end
end

And also applications_controller.rb , specifically the 'create' action which is what I'm trying to test. 还有applications_controller.rb ,特别是我正在尝试测试的'create'动作。 It's fairly ugly at the moment because I'm using state_machine and overriding the delete method. 它目前相当丑陋,因为我正在使用state_machine并覆盖delete方法。

  def create
    # this needs to be cleaned up and use accepts_attributes_for
    @application = Application.new(params[:application])
    @environments = params[:application][:environment_ids]
    @application.environment_ids<<@environments unless @environments.blank?

    if params[:site_bindings] == "new"
      @site = Site.new(:name => params[:application][:name])
      @environments.each do |e|
        @site.siteenvs << Siteenv.new(:environment_id => e)
      end
    end

    if @site
      @application.sites << @site
    end

    if @application.save
      if @site
        @site.siteenvs.each do |se|
          appenv = @application.appenvs.select {|e| e.environment_id == se.environment_id }
          se.appenv = appenv.first
          se.save
        end
      end
      flash[:success] = "New application created."
      respond_with(@application, :location => @application)
    else
      render 'new'
    end

    # super stinky :(
    @application.change_servers_on_appenvs(params[:servers]) unless params[:servers].blank?
    @application.save
  end

I've looked at the source code here: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb , and it seems it should respond correctly, as well as a number of questions on stack overflow that seem to have similar issues and possible solutions, but none work for me. 我在这里查看了源代码: https//github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb ,它似乎应该正确响应,以及堆栈溢出问题的数量似乎有类似的问题和可能的解决方案,但没有一个适合我。

What am I doing wrong? 我究竟做错了什么?

I realize that setting :format => :json is one solution (as noted above). 我意识到设置:format => :json是一种解决方案(如上所述)。 However, I wanted to test the same conditions that the clients to my API would use. 但是,我想测试客户端到API的相同条件。 My clients would not be setting the :format parameter, instead they would be setting the Accept HTTP header. 我的客户端不会设置:format参数,而是设置Accept HTTP标头。 If you are interested in this solution, here is what I used: 如果您对此解决方案感兴趣,请使用以下内容:

# api/v1/test_controller_spec.rb
require 'spec_helper.rb'
describe Api::V1::TestController do
  render_views
  context "when request sets accept => application/json" do
    it "should return successful response" do
      request.accept = "application/json"
      get :test
      response.should be_success
    end
  end
end

Try moving the :format key inside the params hash of the request, like this: 尝试在请求的params哈希中移动:format键,如下所示:

describe ApplicationsController do
  render_views
  disconnect_sunspot

  let(:application) { Factory.create(:application) }

  subject { application }

  context "JSON" do

    describe "creating a new application" do

      context "when not authorized" do
        it "should not allow creation of an application" do
          params = { :format => 'json', :application => { :name => "foo", :description => "bar" } }
          post :create, params 
          Expect(Application.count).to eq(0)
          expect(response.status).to eq(403)
          expect(JSON.parse(response.body)["status"]).to eq("error")
          expect(JSON.parse(response.body)["message"]).to match(/authorized/)
        end 


      end 

      context "authorized" do
      end 
    end
  end
end

Let me know how it goes! 让我知道事情的后续! thats the way I have set my tests, and they are working just fine! 这就是我设置测试的方式,他们工作得很好!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用RSpec在我的Rails应用程序中测试JQuery-UI Sortable的控制器交互? - How do I test JQuery-UI Sortable's controller interaction in my Rails app using RSpec? 如何使用curl测试我的Rails控制器创建动作..还是可以使用rspec? - how do I use curl to test my Rails controller create action.. or can I use rspec? 如何在带有rspec的Rails控制器中测试关联? - How do I test association in rails controller with rspec? 如何在RSpec中将此结果与我的Controller测试匹配 - How do I match this result in RSpec for my Controller test 如何使用 rspec 测试 controller 方法? - how do I test controller method using rspec? 如何使用 RSpec Rails 4.0 使用特定的 url 测试 json 格式? - How to test json format with specific url use RSpec Rails 4.0? Rails 3.1 Rspec Rails 2-如何测试此控制器操作? - Rails 3.1 Rspec Rails 2 - How can I test this controller action? Rspec rails:如何测试一次控制器操作是否正确地使用修改后的参数重定向到其自身? - Rspec rails: How do I test if a controller action redirects correctly to itself with modified params once? RSpec / Rails - 如何测试ApplicationController中的方法是否被调用(当我测试子类控制器时)? - RSpec / Rails - How do I test that a method in ApplicationController is called (when I'm testing a subclassed controller)? 我如何告诉我的Rails控制器使用方法的format.json部分而不是format.html分支? - How do I tell my Rails controller to use the format.json part of my method instead of the format.html branch?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM