Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何仅测试重定向到的URL的一部分(使用assert_redirected_to)?_Ruby On Rails_Ruby_Testing - Fatal编程技术网

Ruby on rails 如何仅测试重定向到的URL的一部分(使用assert_redirected_to)?

Ruby on rails 如何仅测试重定向到的URL的一部分(使用assert_redirected_to)?,ruby-on-rails,ruby,testing,Ruby On Rails,Ruby,Testing,在Rails应用程序的功能测试中,我想测试我被重定向到的位置。预期的URL指向外部资源(这意味着它不是我的应用程序的一部分) URL如下所示:https://my.url.com/foo?bar1=xyz&bar2=123 不幸的是,我无法预测参数,因为它们是由外部资源生成的。* 但是,URL的其余部分始终保持不变:https://my.url.com/foo 对于这种测试,我通常使用assert\u redirected\u to,但这需要整个URL,包括参数 有人能想出另一种方法来测试重定向

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

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

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

对于这种测试,我通常使用
assert\u redirected\u to
,但这需要整个URL,包括参数

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

(URL不在
分配
哈希中)


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

关于这一点,有两个简单的想法:

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

2) 如果您的功能测试实际上没有连接到外部应用程序,那么您无论如何都是在伪造它,因此我将跳过测试重定向URL,而只使用assert_response:redirect测试重定向。或者,创建一个模拟,返回URL进行重定向,就像它是外部应用一样,但这样做的方式可以从中获取参数


也就是说,不要过于沉迷于测试,以至于你觉得必须涵盖每一个可能的场景。

这个怎么样?它包装
assert\u redirected\u to
,以允许
Regexp
作为第一个参数。如果您试图将
Regexp
散列
匹配,则这将不起作用——不过,只能将
字符串
匹配。这样做需要更多的工作

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

http请求命令,如
post
get
等,在调用它们时创建一个名为
@response
的实例变量*
@response
本身包含一个名为
redirect\u url
的方法,该方法存储您被重定向到的url(以防您确实被重定向)

因此,我可以使用一个普通的
断言\u匹配
将正则表达式与
@response.redirect\u url
进行比较:

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

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

我使用以下方法忽略任何查询字符串参数。它基于
assert\u重定向到

# 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
新的和改进的! Rails从6.1开始提供正则表达式匹配

你可以打个电话

assert_redirected_to %r(\Ahttp://example.org/funky_cold_medina/\d+)
RSpecRails只是委托给这个方法,所以即使没有文档记录,它也可以工作

subject { post some_path, params: { chunky_bacon: true} }
it "puts the lotion on itself" do
  expect(subject).to redirect_to( %r(/catch_the_puppy/\d+) )
end

+谢谢你给我指出了正确的方向。你的回答帮助我找到了自己的答案。:-)谢谢你很有先见之明。Rails 6.1现在实际上实现了这一点。我添加了一个详细的回复。谢谢你的想法。你可能是对的,我不应该对考试太着迷。我认为在我的例子中,测试我被重定向到的正确URL真的没有那么重要。然而,我很好奇,是否有可能解决这个问题。为了子孙后代:您可以使用
%r{https://my.url.com/foo}
构造正则表达式而不必转义斜杠。