Rails Rspec redirect_to弹回到根目录

时间:2012-08-13 14:29:07

标签: ruby-on-rails routes rspec2

我正在Rspec2,Rails 3中进行控制器测试,基本上我在通信控制器中有一个编辑操作,所以如果有人想要编辑批量电子邮件,他们可以处于草稿模式。如果已经批准或发送,则无法进行编辑。

我的控制器看起来像这样

class CommunicateController < ApplicationController
before_filter :setup

require_role 'view_communication'
#require_role 'edit_communication', :only => [:new, :edit, :create, :update, :destroy] Role not implemented
require_role 'approve_communication', :only => :approve
require_role 'send_communication', :only => :distribute

 ...

# GET /communications/1/edit
def edit
  if @communication.status == 'Sent' || @communication.status == 'Approved'
    flash[:error] = 'Cannot edit communication once it has been either approved or sent.'
    redirect_to(communicate_path(@communication))
 end
end

 ...

private
  def setup
    @communication = current_account.communications.find(params[:id]) if params[:id]
  end
end

现在它在生产中工作,一切都很酷。问题是现在我必须测试它。

我的测试看起来像这样:

describe CommunicateController, "#edit" do
  context "when i am editing a pre approved bulk email" do
  before(:each) do
    @account = FactoryGirl.create(:account)
    @user = FactoryGirl.create(:superuser, :accounts => [@account])
    controller.stub(:current_account).and_return(@account)
    @supplier = FactoryGirl.create(:supplier, :account => @account)
    @other_supplier = FactoryGirl.create(:supplier, :account => @account)
    @supplier_report = FactoryGirl.create(:supplier_report, :reportable => @account)
    @communicate = FactoryGirl.create(:communication, :account => @account, :supplier_report => @supplier_report)
    controller.stub(:setup).and_return(@communicate)
  end

  it "denies edit access if the bulk email is sent" do
    @communicate.status = 'Sent'
    get :edit, :id => @communicate.id 
    response.should redirect_to(communicate_path(@communicate))
  end

  it "denies edit access if the bulk email has been approved" do
    @communicate.status = 'Approved'
    get :edit, :id => @communicate.id
    response.should redirect_to(communicate_path(@communicate))
  end

  it "allows edits to Draft bulk email" do
    @communicate.status = 'Draft'
    get :edit, :id => @communicate.id
    response.should redirect_to(edit_communicate_path)
  end

 end
end

正如您所看到的,为此特定测试设置环境非常复杂,并且满足所有要求。但是当我运行测试时它会给我以下错误:

Failure/Error: response.should redirect_to(communicate_path(@communicate))
Expected response to be a redirect to <http://test.host/communicate/1> but was a redirect to <http://test.host/>

但是对于所有三个测试都有相同的错误。所以代码工作,测试似乎正在寻找正确的路线,我只是不知道为什么它寻找根路线。

抱歉,如果这是一个简单的错误,我只在轨道上编程了几个月,这实际上是我在rspec中的第一个控制器测试,所以我不确定要查找什么,或者我的测试是否状态良好。

非常感谢任何帮助或指导

1 个答案:

答案 0 :(得分:1)

做类似

的事情
grep -ri "redirect_to root_path" ./

在你的app目录中,你可以看到你在哪里重定向到根路径并尝试用它调试

实际调用的是那些动作吗?在编辑动作开始时放一些“打印'进入!'”,我猜它不会在控制台上打印任何东西,因为它甚至没有在那里打印,如果是这种情况你可能有一些before_filter或require_role或者你是什么东西你的考试不见了

顺便说一下(因为你也问你的规格是否状态良好),你应该模拟你的模型并存根你需要的方法,比如

(在控制器上)

def edit
  unless @communication.can_edit?
    flash[:error] = 'Cannot edit communication once it has been either approved or sent.'
    redirect_to(communicate_path(@communication))
  end
end

(在模型上)

def can_edit?
  ('Sent','Approved').include? status
end

(然后在规范上)

before(:each) do
  account = mock(:account)
  controller.stub(:current_account).and_return(account)
  communication = mock(:communication)
  communication.stub(:can_edit? => false) #you can override this with true on the allow test
  controller.stub(:setup).and_return(communication)
end

然后你将这两个拒绝测试(发送和批准)移动到通信规范(如果状态是发送',它'返回false'等等)你的控制器测试应该是“它'rdenies访问,如果通信无法编辑'do'

希望有所帮助

编辑:另外,我认为如果你只是在控制器的动作上使用@communication,那么你需要一些辅助方法,如:

def current_communication
  @communication
end

因为您正在设置方法,所以@communication分配永远不会执行,如果您直接使用@communication将为nil