RSpec redirect_to和return vs. redirect_to&&返回

时间:2015-09-25 00:26:16

标签: ruby-on-rails ruby rspec rspec-rails

我有一个控制器在某些条件下在某些点重定向。当我将参数传递给我的控制器规范中的规范帮助器方法(使用最新的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。

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

5 个答案:

答案 0 :(得分:4)

根据the Rails guide

  

请务必使用and return代替&& return,因为由于Ruby语言中的运算符优先级,&& return将无效。

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

redirect_to(root_path) && return

答案 1 :(得分:4)

差异&&andprecedence。高优先级导致ruby解析为

redirect_to(root_path && return)

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

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

(redirect_to root_path) and return

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

答案 2 :(得分:1)

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

因此,请确保为控制器操作提供模板。

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

解释&&and的不同运算符优先级的答案是正确的。但是,检查renderredirect_to的返回值的整个想法是误导性的,Rails指南不应该推荐它

renderredirect_to会因其副作用(他们修改响应)而被调用,而不是因为它们的返回值。如果他们有错误,他们会引发异常,而不是返回虚假值。因此,使用&&and会产生误导。相反,做

redirect_to root_path
return

向读者清楚地说明代码是如何工作的,并避免与操作员一起讨论这些问题。