2011-04-30 77 views
14

我打算在我的项目中同时在请求和响应中使用JSON数据,并且在测试中遇到一些问题。如何在rails中发布JSON数据3功能测试

搜索一段时间后,我发现下面的代码使用curl张贴JSON数据:

curl -H "Content-Type:application/json" -H "Accept:application/json" \ 
    -d '{ "foo" : "bar" }' localhost:3000/api/new 

在控制器我可以访问只需使用params[:foo]这是很容易的JSON数据。但对于功能测试,我只能找到postxhr(别名为xml_http_request)。

如何在rails中编写功能测试以达到与使用curl相同的效果?或者我应该以其他方式进行测试?

这是我试过的。我发现xhr的实现在action_controller/test_case.rb,并试图添加jhr方法,只需更改'Conetent-Type'和'HTTP_ACCEPT'。 (添加于test/test_helpers.rb

def json_http_request(request_method, action, parameters = nil, session = nil, flash = nil) 
    @request.env['Content-Type'] = 'Application/json' 
    @request.env['HTTP_ACCEPT'] ||= [Mime::JSON, Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') 
    __send__(request_method, action, parameters, session, flash).tap do 
    @request.env.delete 'Content-Type' 
    @request.env.delete 'HTTP_ACCEPT' 
    end 
end 
alias jhr :json_http_request 

我用这个以同样的方式作为xhr,但它不工作。我检查了@response对象,看到身体是" "

我还找了堆栈溢出one similar question但它的轨道2与张贴原始数据,答案不轨工作3

+1

像往常一样写功能测试,只需指定请求格式,如post:new,:foo =>'bar',:format =>'json' – taro 2011-04-30 13:16:33

+0

我试过了。但是响应的内容类型是“text/html”,而body是'“”'。当使用''xhr''做post时,响应的content-type是“application/json”,body是JSON数据。 – cyfdecyf 2011-05-01 15:17:59

回答

9

只要指定适当的内容类型:

post :index, '{"foo":"bar", "bool":true}', "CONTENT_TYPE" => 'application/json' 

JSON数据应作为一个字符串,而不是一个哈希。 看着堆栈跟踪运行测试,你可以获取有关要求编制更多的控制权: ActionDispatch ::积分:: RequestHelpers.post =>ActionDispatch::Integration::Session.process => Rack::Test::Session.env_for

指定:格式不工作,因为要求去为“应用/ x-www-form-urlencoded',并且json没有正确处理请求主体。

+0

我可能是错的,但我认为你可以这样做:type =>:json – FreeCandies 2011-10-28 10:16:58

+7

直接构造字符串将得到以下错误:“{\”foo \“:\”bar中的'NoMethodError:undefined method'symbolize_keys' \“}”:String'' – cyfdecyf 2011-12-17 10:51:01

+0

我使用机架测试gem来做这样的测试,因为它简化了许多请求的身份验证。在场景文件的顶部添加'require'rack/test''。 – Grimmo 2011-12-22 12:56:00

0

由于@taro的意见建议以上,在功能性和集成测试适合我的语法是:

post :create, {param1: 'value1', param2: 'value2', format: 'json'} 

(大括号并不总是必要的,但有时这是行不通的如果他们错过,所以我总是将它们添加)

这里是和request.format看PARAMS像那种一职。

PARAMS: {“参数1” =>“VALUE1” “param2”=>“value2”,“format”=>“json”,“controller”=>“thing S”, “行动”=> “创建”}

request.format: 应用/ JSON

10

我发现,这不正是我想要的东西 - 后JSON到控制器的动作。

post :create, {:format => 'json', :user => { :email => "[email protected]", :password => "foobar"}} 
3

假设你有一个控制器名为API,一个叫新的方法,而你在测试的API控制器是:

@request.env["RAW_POST_DATA"] = '{ "foo" : "bar" }' 
post :new 

奏效了我。

1

这是一段让我发布json数据来测试我自己的应用程序的代码片段。轨道3

port = Rails.env.production? ? 80 : 3000 
uri = URI.parse(Rails.application.routes.url_helpers.books_url(:host => request.host, :port => port, :format => :json)) 
http = Net::HTTP.new(uri.host, uri.port) 
request = Net::HTTP::Post.new(uri.request_uri) 
request.content_type = 'application/json' 
request.body = @json_data 
response = http.request(request) 
@result = response.body 

希望这有助于他人

0

最好的答案我可以拿出来,这是你不

它是否是故意的IT方面也许是好的轨道不会为你实现这个。

在功能测试中,你真的只想测试你的控制器和而不是 rails的反序列化方法,或者甚至路由和MIME检测都设置正确,这些都属于IntegrationTest。

所以对于你的控制器,不要通过JSON只是像你通常传递你的params散列。也许增加:格式作为参数,如果您需要检查并以不同方式响应。

如果你要测试的完整的堆栈移动到一个IntegrationTest

10

铁轨5,要做到这一点的方法是:

post new_widget_url, as: :json, params: { foo: "bar" } 

目前尚不清楚,我认为它集Content-type头正确 - 在这些集成测试中涉及很多方法 - 但请求数据似乎确实正确地传递给控制器​​。

+0

这是Rails 5的新正确答案。旧方法提供了“DEPRECATION WARNING: ActionDispatch :: IntegrationTest HTTP请求方法在未来的Rails版本中将只接受以下关键字参数: params,headers,env,xhr,作为 ' – zmanw 2016-09-28 15:04:29

+0

请求代码可以在_actionpack-5.0.0.1/lib/action_dispatch/testing/integration.rb_ line 326方法'进程'。但[doc](http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html#method-i-get)没有提及'as'参数 – Benj 2016-11-01 14:54:33

相关问题