Rails功能测试:在POST请求中发送URL查询参数
我在这样的Rails功能测试中发送POST请求:
post :create, collection: { name: 'New Collection' }
按照预期, collection
将作为JSON编码的表单数据发送。
我无法弄清楚的是如何向URL添加查询。 该文档说我可以访问请求对象并在发送之前进行修改。 所以我试过这个:
@request.GET[:api_key] = 'my key'
post :create, collection: { name: 'New Collection' }
但是, :api_key
永远不会出现在服务器上的request.GET
散列中。 (但是,当我通过另一个HTTP客户端发送它时,它会执行此操作。)
首先澄清一些事情:尽管请求不能同时使用GET和POST,但在使用POST时不会阻止使用查询字符串和正文表单数据。 你甚至可以在查询字符串中有一个包含所有参数的POST和一个空体,尽管这听起来很不寻常。
Rails支持这种情况,事实上,你可以使用POST请求轻松发送表单,并在表单的操作中仍然有查询。 查询将可以通过request.GET
散列(它是query_string
的别名)来访问,而POST正文使用request.POST
散列( request_parameters
的别名)。 params
哈希实际上是由组合的GET
和POST
哈希构建的。
但是,从我的研究看来, Rails在功能控制器测试中不支持在POST请求中传递查询字符串 。 虽然在任何文档或github上的已知问题中,我都找不到任何关于此的内容,但源代码非常清晰。 在下面的文本中,我假设你使用Rails 4。
为什么它不起作用
功能控制器测试的问题在于它们不使用实际的请求/响应,而是模拟HTTP握手:请求被模拟,其参数填充到适当的位置,并且给定的控制器操作简单地称为普通的ruby方法。 所有这些都是在action_controller/test_case
类中完成的。
事实证明,这种模拟不适用于您的具体情况,原因有两个:
运行测试时传入的参数都交给无论对request_parameters
,即request.POST
使用时哈希post
请求或到query_string
(即request.GET
)用于get
测试请求。 在单次测试运行期间,无法设置这两个哈希值。
这实际上是有道理的,因为函数测试中的get
, post
等辅助函数只接受参数的单个散列值,所以内部测试代码无法知道如何将它们分离为两个散列值。
确实,在使用@request
变量运行测试之前,可以设置请求,但只有某种程度上,您可以设置标题。 但是你不能设置请求的内部属性 ,因为它们在测试运行期间被回收 。 回收在这里完成,它将重置请求对象和底层机架请求对象的所有内部变量。 所以如果你尝试设置request @request.GET[:api_key] = 'my key'
这样的请求GET参数,它将不会产生任何影响,因为表示这个hash的内部变量在回收期间会被擦除。
解决方案/解决方法
放弃功能测试,并选择集成测试 。 集成测试允许将机架环境变量与主要参数分开设置。 以下集成测试通过QUERY_STRING
rack env变量,除了正常的post body参数之外,应该完美地工作:
class CollectionsTest < ActionDispatch::IntegrationTest
test 'foo' do
post collections_path, { collection: { name: 'New Collection' } },
{ "QUERY_STRING" => "api_key=my_api_key" }
# this proves that the parameters are recognized separately in the controller
# (you can test this in you controller as well as here in the test):
puts request.POST.inspect
# => {"collection"=>{"name"=>"New Collection"}}
puts request.GET.inspect
# => {"api_key"=>"my_api_key"}
end
end
您仍然可以在集成测试中使用功能测试中的大部分功能。 例如,您可以使用assigns
散列来测试控制器中已分配的实例变量。
Rails 5支持集成测试不赞成使用功能控制器测试,而且这些功能测试支持的Rails 5.1将移出到单独的gem,这一事实也支持transition参数。
尝试Rails 5:虽然功能测试将被弃用,但它的源代码似乎已经在rails主机中大量重写,并且例如请求的再循环不再被使用。 所以你可以尝试一下,在测试设置期间尝试设置请求的内部变量。 我还没有测试过它。
当然,您可以尝试对功能测试进行猴式修补,以便它支持在测试中定义query_string
和request_parameters
哈希的单独参数。
我会去集成测试路线:)。
我假设控制器被命名为CollectionsController
,并且其create
操作的路径是/collections
(如果不是,您只需修改示例波纹管)
而且我还假设你在一个请求规范中
这应该工作:
post '/collections?api_key=my_key', collection: { name: 'New Collection' }
第二个参数post
是你会收到在控制器则params的哈希值。 只要这样做:
post :create, collection: { name: 'New Collection' }, more_params: 'stuff', and_so_on: 'things'
这些参数将在控制器中提供:
params[:and_so_on] == 'things'
链接地址: http://www.djcxy.com/p/41091.html
上一篇: Rails functional test: sending URL query parameters in POST request