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

时间:2011-04-30 10:20:32

标签: ruby-on-rails json functional-testing

我计划在项目中的请求和响应中使用JSON数据,并在测试中遇到一些问题。

搜索一段时间后,我发现以下代码使用curl发布JSON数据:

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

在控制器中,我可以使用params[:foo]简单地访问JSON数据,这非常简单。但是对于功能测试,我只找到postxhrxml_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对象并看到正文为" "

我还在Stack Overflow上找到了one similar question,但它是针对rails 2的,并且发布原始数据的答案在rails 3中不起作用。

7 个答案:

答案 0 :(得分:14)

从Rails 5开始,执行此操作的方法是:

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

这也会正确设置Content-type标题(到application/json)。

答案 1 :(得分:10)

我发现这正是我想要的 - 将JSON发布到控制器的动作。

post :create, {:format => 'json', :user => { :email => "test@test.com", :password => "foobar"}}

答案 2 :(得分:9)

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

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

Json数据应该作为字符串,而不是哈希。 查看运行测试的堆栈跟踪,您可以获得对请求准备的更多控制: ActionDispatch :: Integration :: RequestHelpers.post => ActionDispatch::Integration::Session.process => Rack::Test::Session.env_for

指定:格式不起作用,因为请求变为'application / x-www-form-urlencoded'并且json未正确解析处理请求正文。

答案 3 :(得分:3)

假设您有一个名为api的控制器,一个名为new的方法,并且您正在测试api控制器:

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

为我做了诀窍。

答案 4 :(得分:1)

这是一个片段,让我发布json数据来测试我自己的应用程序。 rails 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

希望这有助于其他人

答案 5 :(得分:0)

正如@taro在上面的评论中所建议的,在功能和集成测试中适用于我的语法是:

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

(花括号并不总是必要的,但有时如果它们丢失则不起作用,所以我总是添加它们。)

以下是params和request.format对于那种帖子的看法:

PARAMS: {“param1”=>“value1”,“param2”=>“value2”,“format”=>“json”,“controller”=>“thing”,“action”=>“创建” }

request.format: 应用/ JSON

答案 6 :(得分:0)

我能想到的最佳答案是你没有

无论是否有意,导轨都不会为你实现这一点。

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

所以对于你的控制器,不要像往常那样传递你的params哈希传递JSON。也许添加:格式作为参数,如果你需要检查并作出不同的反应。

如果要测试完整堆栈移动到IntegrationTest