如何只测试我重定向到的URL的一部分(使用assert_redirected_to)?

时间:2010-01-08 00:43:31

标签: ruby-on-rails ruby testing

在我的Rails应用程序的功能测试中,我想测试我被重定向到的位置。预期的URL指向外部资源(这意味着它不是我的应用程序的一部分)。

网址如下所示:https://my.url.com/foo?bar1=xyz&bar2=123

不幸的是我无法预测参数,因为它们是由外部资源生成的。*
但是,网址的其余部分始终保持不变:https://my.url.com/foo

我通常使用assert_redirected_to进行此类测试,但这需要整个网址,包括参数。

有人能想到另一种方法来测试重定向,但只检查没有参数的URL的第一部分吗?

(网址不在assigns哈希)

*(我对应用程序进行API调用,使用我将重定向的URL进行响应)

4 个答案:

答案 0 :(得分:18)

postget等http请求命令在调用*时会创建一个名为@response的实例变量。 @response本身包含一个名为redirect_url的方法,该方法存储您已重定向到的URL(如果您确实已被重定向)。

因此,我可以使用普通assert_match将正则表达式与@response.redirect_url进行比较:

post :my_action_to_test
assert_response :redirect
assert_match /https:\/\/my.url.com\/foo/, @response.redirect_url

*(实际上,这些http方法只使用私有方法process,它创建@response变量。)

答案 1 :(得分:2)

对此有两个快速的想法:

1)如果您的功能测试实际连接到外部应用程序,为什么不像通常那样从中获取params并测试重定向是否正确?

2)如果您的功能测试实际上没有连接到外部应用程序,那么您无论如何都要伪装它,所以我只是跳过测试重定向URL并尝试使用assert_response:redirect测试重定向。或者,创建一个模拟,返回重定向的URL,就好像它是外部应用程序一样,但是这样做可以让你从中获取params。

也就是说,不要因为你认为必须涵盖每一种可能的情况而进行测试。

答案 2 :(得分:1)

这个怎么样?它包装assert_redirected_to以允许Regexp作为第一个参数。但是,如果您尝试将RegexpHash匹配 - 只有String,则无效。这样做会花费更多的工作。

ActionController::TestCase.class_eval do

  old_assert_redirected_to = method(:assert_redirected_to)

  define_method(:assert_redirected_to) do |*args|
    if args.[0].kind_of?(Regexp)
      assert_response(:redirect, args[1])
      assert args[0] === @response.redirected_to
    else
      old_assert_redirected_to.bind(self).call(*args)
    end
  end

end

答案 3 :(得分:0)

我使用以下方法忽略任何查询字符串参数。它基于assert_redirected_to

的官方实施
# ignores any query string params eg. notice or alert messages for flash
def custom_assert_redirected_to(path)
  assert_response :redirect

  if path === Regexp
    url = path
  else
    url = ActionController::Redirecting._compute_redirect_to_location(@request, path)
  end

  assert_equal url, @response.location.split("?").first
end