RSpec redirect_to 和 return 对比 redirect_to && return

RSpec redirect_to and return vs. redirect_to && return

我有一个控制器,可以在特定条件下在特定点重定向。当我将参数传递给控制器​​规范中的规范辅助方法(使用最新的 RSpec)以触发这些条件时,我得到一个

ActionView::MissingTemplate

错误。在仔细检查我应该重定向时,我做了如下一行:

redirect_to root_path && return

然后在我的测试套件中抛出异常。我在应该调用的控制器的索引函数中放置了一个断点(我重定向到的路由指向)并且它从未在我的测试套件中调用过。当我在我的开发环境和生产环境中 运行 它时,这段代码似乎可以工作,但对于这个测试,它不会让步。有什么想法吗?

我的测试看起来像这样:

describe TestController do
  it 'redirects properly with failure' do
    get :create, provider: 'test', error: 'access_denied'
    expect(response.body).to match 'test'
  end
end

编辑:

更新!

似乎将我的重定向更改为

redirect_to root_path and return

在RSpec工作。

我不知道为什么 && 运算符的优先级违反规范。有人对这里发生的事情有解释吗?

测试控制器时模板必须存在,因为 视图默认存根。 请参阅 RSpec Documentation

因此,请确保您拥有用于控制器操作的模板。

默认控制器规范不遵循重定向。因此永远不会调用您的索引操作。相反,您应该检查它是否从服务器收到了正确的重定向命令:

describe TestController do
  it 'redirects properly with failure' do
    get :create,
        provider: 'test',
        error: 'access_denied'
    expect(response).to redirect_to root_path
  end
end

这称为测试隔离:您只测试创建操作是否重定向到特定点。应该在控制器的索引规范而不是创建规范中测试索引操作的真正工作方式。

根据the Rails guide

Make sure to use and return instead of && return because && return will not work due to the operator precedence in the Ruby Language.

如果您更喜欢使用 &&,请将 render 的参数括在括号中:

redirect_to(root_path) && return

&& 的差异 precedence 高于 and。高优先级导致 ruby 将其解析为

redirect_to(root_path && return)

方法当然必须在方法本身被调用之前评估它们的参数,所以在这种情况下 redirect_to 永远不会被调用,因为 ruby 首先点击 return

另一方面,and 的较低优先级意味着它被解析为

(redirect_to root_path) and return

这是您想要的 - 首先进行重定向,然后 return。

解释 &&and 不同运算符优先级的答案就目前而言是正确的。但是,检查 renderredirect_to 的 return 值的整个想法具有误导性,Rails 指南不应推荐它.

renderredirect_to 被调用是因为它们的副作用(它们修改响应),而不是因为它们的 return 值。如果它们有错误,它们会引发异常,而不是 return 虚假值。所以使用 &&and 是一种误导。相反,做

redirect_to root_path
return

让读者清楚代码是如何工作的,避免所有这些与运算符的混淆。