假设我有FoosController
redirect_to_baz
方法。
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 })
我查看了documentation,我尝试搜索response.parameters
,但我没有找到类似的内容。即使Hash#to_query
似乎也无法解决这个问题。
非常感谢任何帮助。
答案 0 :(得分:25)
从documentation,预期的重定向路径可以匹配正则表达式:
expect(response).to redirect_to %r(\Ahttp://example.com)
要验证重定向位置的查询字符串似乎有点复杂。您可以访问响应的位置,因此您应该可以执行此操作:
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"}
从中可以直接验证重定向参数是否正确:
expect(redirect_params).to eq("foo" => "1", "baz" => "3", "bar" => "2")
# => true
如果你不得不多次执行这种逻辑,那么将它们全部包装到自定义的rspec匹配器中肯定会很方便。
答案 1 :(得分:5)
您是否能够使用路径助手而不是普通字符串?如果是这样,您可以将哈希参数传递给路由助手,它们将被转换为查询字符串参数:
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散列...
答案 2 :(得分:2)
我需要类似的东西,结果是这样:
能够编写测试,而不必担心查询参数的顺序。
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