RSpec测试使用GET参数重定向到URL
假设我有一个带有redirect_to_baz
方法的FoosController
。
class FoosController < ApplicationController def redirect_to_baz redirect_to 'http://example.com/?foo=1&bar=2&baz=3' end end
我正在使用spec/controllers/foos_controller_spec.rb
测试它:
require 'spec_helper' describe FoosController, :type => :controller do describe "GET redirect_to_baz" do it "redirects to example.com with params" do get :redirect_to_baz expect(response).to redirect_to "http://example.com/?foo=1&bar=2&baz=3" end end end
有用。 但是,如果有人交换查询字符串参数(例如http://example.com/?bar=2&baz=3&foo=1
),则测试失败。
测试这个的正确方法是什么?
我想做的事情如下:
expect(response).to redirect_to("http://example.com/", params: { foo: 1, bar: 2, baz: 3 })
我查看了文档 ,我尝试搜索response.parameters
,但我没有找到类似的东西。 即使是Hash#to_query
似乎也没有解决这个问题。
任何帮助将不胜感激。
从文档中 ,预期的重定向路径可以匹配正则表达式:
expect(response).to redirect_to %r(\Ahttp://example.com)
要validation重定向位置的查询字符串似乎有点复杂。 您可以访问响应的位置,因此您应该能够这样做:
response.location # => http://example.com?foo=1&bar=2&baz=3
您应该能够像这样提取查询字符串参数:
redirect_params = Rack::Utils.parse_query(URI.parse(response.location).query) # => {"foo"=>"1", "bar"=>"2", "baz"=>"3"}
从中可以直接validation重定向参数是否正确:
expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2") # => true
如果你不得不多次执行这种逻辑,那么将它们全部包装到自定义的rspec匹配器中肯定会很方便。
你能使用你的路线助手而不是普通的弦吗? 如果是这样,您可以将哈希参数传递给路由助手,它们将转换为查询字符串参数:
root_url foo: 'bar', baz: 'quux' => "http://www.your-root.com/?baz=quux&foo=bar" expect(response).to redirect_to(root_url(foo: 'bar', baz: 'quux'))
这有帮助,还是仅限于使用字符串而不是路由助手?
另一个想法是你可以直接断言params散列中的值而不是url +查询字符串,因为查询字符串params将序列化为params散列…
我需要类似的东西,最后得到这个:
能够编写测试而不用担心查询参数排序。
expect(response.location).to be_a_similar_url_to("http://example.com/?beta=gamma&alpha=delta")
将以下内容放入./spec/support/matchers/be_a_similar_url_to.rb
RSpec::Matchers.define :be_a_similar_url_to do |expected| match do |actual| expected_uri = URI.parse(expected) actual_uri = URI.parse(actual) expect(actual_uri.host).to eql(expected_uri.host) expect(actual_uri.port).to eql(expected_uri.port) expect(actual_uri.scheme).to eql(expected_uri.scheme) expect(Rack::Utils.parse_nested_query(actual_uri.query)).to eql(Rack::Utils.parse_nested_query(expected_uri.query)) expect(actual_uri.fragment).to eql(expected_uri.fragment) end # optional failure_message do |actual| "expected that #{actual} would be a similar URL to #{expected}" end # optional failure_message_when_negated do |actual| "expected that #{actual} would not be a similar URL to #{expected}" end end