Ruby on rails 如何仅测试重定向到的URL的一部分(使用assert_redirected_to)?
在Rails应用程序的功能测试中,我想测试我被重定向到的位置。预期的URL指向外部资源(这意味着它不是我的应用程序的一部分) URL如下所示: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,包括参数 有人能想出另一种方法来测试重定向
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}
构造正则表达式而不必转义斜杠。