繁体   English   中英

如何在 rails 3 功能测试中发布 JSON 数据

[英]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 数据,这非常简单。 但是对于功能测试,我只找到postxhrxml_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM