1

我正在 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/>

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

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

任何帮助或指导将不胜感激

4

1 回答 1

1

做类似的事情

grep -ri "redirect_to root_path" ./

在您的应用程序目录中,您可以看到您在哪里重定向到根路径并尝试使用它进行调试

这些动作实际上被调用了吗?在编辑操作开始时放一些“打印'输入!'”,我想它不会在控制台上打印任何东西,因为它甚至没有到达那里,如果是这种情况,你可能有一些 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 等等),并且您的控制器测试应该是“如果无法通信,它将拒绝访问编辑“做”

希望能帮助到你

编辑:另外,我认为如果您只在控制器的操作上使用@communication,您的规范将需要一些辅助方法,例如:

def current_communication
  @communication
end

由于您正在对 setup 方法进行存根,因此永远不会执行 @communication 分配,如果您直接使用它,@communication 将为零

于 2012-08-13T16:56:40.017 回答