Rspec을 사용하여 Rails 3.0.11 컨트롤러의 JSON 형식을 테스트하려면 어떻게 해야 합니까?
웹을 뒤졌지만 안타깝게도 Rspec이 JSON API를 테스트하기 위해 콘텐츠 타입을 올바르게 전송하도록 할 수 없는 것 같습니다.템플릿에는 RABL gem, Rails 3.0.11 및 Ruby 1.9.2-p180을 사용하고 있습니다.
컬 출력은 정상적으로 동작합니다(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."}
테스트 케이스의 샘플:
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
이러한 테스트는 통과하지 않습니다.항상 리다이렉트 되고 콘텐츠 타입은 항상text/html
before block의 타입을 지정하는 방법에 관계없이, 다음과 같이 합니다.
# 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
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)>'
보시다시피 'application/json'을 지정하려고 하는데 HTML 형식의 302 리다이렉트를 받습니다.
여기 제 것이 있습니다.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
그리고 또applications_controller.rb
특히 '만들기' 액션을 테스트하려고 합니다.지금 이 순간은 꽤 보기 흉합니다.state_machine
삭제 방법을 덮어씁니다.
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
여기 소스코드 https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb,를 확인했습니다.또, 스택 오버플로에 관해서, 같은 문제와 생각할 수 있는 해결책이라고 생각되는 질문도 다수 있습니다만, 어느 쪽도 효과가 없습니다.
내가 뭘 잘못하고 있지?
나는 그 설정을 깨달았다.:format => :json
(위에서 설명한 바와 같이)는 하나의 솔루션입니다.다만, 저는 제 API의 클라이언트가 사용하는 것과 같은 조건을 테스트하고 싶었습니다.내 고객은 이 설정을 하지 않을 것이다.:format
파라미터가 설정되어 있습니다.Accept
HTTP 헤더이 솔루션에 관심이 있으시다면, 제가 사용한 것은 다음과 같습니다.
# 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
를 이동해 보세요.: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
어떻게 되어가는지 알려줘! 그게 내가 시험지를 세팅한 방법이고, 그들은 잘 작동하고 있어!
대답이 너무 늦었네요!사용할 수 있는 동안render_views
컨트롤러에서 json을 가져오려면 뷰 테스트를 작성할 수도 있습니다.
spec/views/posts/show.json.jbuilder_spec.rb
require 'rails_helper'
RSpec.describe 'posts/show.json', type: :view do
subject(:json) { JSON.parse render }
before { assign(:post, post) }
let(:post) { Post.create title: 'New Post' }
it 'has the title attribute' do
expect(json).to include 'title' => post.title
end
end
언급URL : https://stackoverflow.com/questions/9576756/using-rspec-how-do-i-test-the-json-format-of-my-controller-in-rails-3-0-11
'sourcecode' 카테고리의 다른 글
Block.json이 잘못된 경로를 반환함 (0) | 2023.02.28 |
---|---|
$.getJ에서 변수를 반환하려면 어떻게 해야 합니까?SON 함수 (0) | 2023.02.28 |
do_action과 add_action은 어떻게 작동합니까? (0) | 2023.02.28 |
Woocommerce REST API에서 범주별로 제품 가져오기 (0) | 2023.02.28 |
woocommerce 커스텀 오더 상태를 추가하려면 어떻게 해야 하나요? (0) | 2023.02.28 |