我正在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中的第一个控制器测试,所以我不确定要查找什么,或者我的测试是否状态良好。非常感谢任何帮助或指导
答案 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