我计划在项目中的请求和响应中使用JSON数据,并在测试中遇到一些问题。
搜索一段时间后,我发现以下代码使用curl
发布JSON数据:
curl -H "Content-Type:application/json" -H "Accept:application/json" \
-d '{ "foo" : "bar" }' localhost:3000/api/new
在控制器中,我可以使用params[:foo]
简单地访问JSON数据,这非常简单。但是对于功能测试,我只找到post
和xhr
(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
对象并看到正文为" "
。
我还在Stack Overflow上找到了one similar question,但它是针对rails 2的,并且发布原始数据的答案在rails 3中不起作用。
答案 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