[英]How to post JSON data in rails 3 functional test
我计划在我的项目中的请求和响应中都使用 JSON 数据,并且在测试中遇到了一些问题。
经过一段时间的搜索,我发现以下代码使用curl
发布 JSON 数据:
curl -H "Content-Type:application/json" -H "Accept:application/json" \
-d '{ "foo" : "bar" }' localhost:3000/api/new
在 controller 中,我可以简单地使用params[:foo]
访问 JSON 数据,这非常简单。 但是对于功能测试,我只找到post
和xhr
( xml_http_request
的别名)。
如何在 rails 中编写功能测试以达到与使用curl
相同的效果? 还是我应该以其他方式进行测试?
这是我尝试过的。 我在action_controller/test_case.rb
中找到了xhr
的实现,并尝试添加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
object 并看到身体是" "
。
我还在 Stack Overflow 上找到了一个类似的问题,但它适用于 rails 2,而发布原始数据的答案在 rails 3 中不起作用。
从 Rails 5 开始,这样做的方法是:
post new_widget_url, as: :json, params: { foo: "bar" }
这也将正确设置Content-type
header (到application/json
)。
我发现这正是我想要的——将 JSON 发布到控制器的操作中。
post :create, {:format => 'json', :user => { :email => "test@test.com", :password => "foobar"}}
只需指定适当的内容类型:
post :index, '{"foo":"bar", "bool":true}', "CONTENT_TYPE" => 'application/json'
Json 数据应将 go 作为字符串,而不是作为 Hash。 查看运行测试的堆栈跟踪,您可以获得对请求准备的更多控制: ActionDispatch::Integration::RequestHelpers.post => ActionDispatch::Integration::Session.process => Rack::Test::Session.env_for
指定:格式不起作用,因为请求 go 为 'application/x-www-form-urlencoded' 并且 json 未正确解析处理请求正文。
假设您有一个controller名为Z8A5DA52ED126447D359E70C05721A8AAAZ,一种名为new的方法,您正在测试Z8A5DA52252525259EB12647D37D359D359D359D359EBEN
@request.env["RAW_POST_DATA"] = '{ "foo" : "bar" }'
post :new
为我做了伎俩。
这是一个片段,让我发布 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
希望这对其他人有帮助
正如@taro 在上面的评论中所建议的那样,在功能和集成测试中对我有用的语法是:
post :create, {param1: 'value1', param2: 'value2', format: 'json'}
(花括号并不总是必需的,但有时如果缺少它们就不起作用,所以我总是添加它们。)
这是此类帖子的 params 和 request.format 的样子:
参数:{"param1"=>"value1", "param2"=>"value2", "format"=>"json", "controller"=>"things", "action"=>"create"}
request.format:应用程序/json
我能想到的最好的答案是你没有
不管是不是故意的,rails 没有为你实现这个可能是件好事。
在功能测试中,你真的只想测试你的 controller 而不是rails 的反序列化方法,甚至路由和 mime 检测都设置正确,这些都属于 IntegrationTest。
因此,对于您的控制器,不要像往常一样传递 JSON 只需传递参数 hash 即可。 如果您需要检查并做出不同的响应,也许还可以添加:格式作为参数。
如果您想测试完整的堆栈,请移至IntegrationTest
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.