使用 rspec 和存根测试控制器时出现问题
我很难使用 before_filters、异常以及一些模拟和存根来测试我的控制器。 这是控制器:
before_filter :get_subject, :only => [:show, :edit, :update, :destroy, :update_field]
before_filter :user_has_to_belongs_to_subject_company, :only => [:show, :edit, :update, :destroy, :update_field]
def show
@messages = @subject.get_user_messages(current_user)
end
private
def get_subject
@subject = Subject.find(params[:id])
end
def user_has_to_belongs_to_subject_company
unless @current_user.company.eql?(@subject.company)
raise "Error: current_user does not belongs to subject's company"
end
end
这是我的规范文件:
require 'spec_helper'
describe SubjectsController do
describe "for signed users" do
before(:each) do
@current_user = Factory(:user)
sign_in @current_user
end
describe "for user belonging to subject's company" do
before(:each) do
@subject = mock_model(Subject)
Subject.stub!(:find).with(@subject).and_return(@subject)
@current_user.stub_chain(:company, :eql?).and_return(true)
@subject.stub!(:company)
end
it "should not raise an exception" do
expect { get :show, :id => @subject }.to_not raise_error
end
end
describe "for user not belonging to subject's company" do
before(:each) do
@subject = mock_model(Subject)
Subject.stub!(:find).with(@subject).and_return(@subject)
@current_user.stub_chain(:company, :eql?).and_return(false)
@subject.stub!(:company)
end
it "should raise an exception" do
expect { get :show, :id => @subject }.to raise_error
end
end
end
end
最后,这是错误消息:
SubjectsController for signed users for user belonging to subject's company should not raise an exception
Failure/Error: expect { get :show, :id => @subject }.to_not raise_error
expected no Exception, got #<RuntimeError: Error: current_user does not belongs to subject's company>
# ./spec/controllers/subjects_controller_spec.rb:19:in `block (4 levels) in <top (required)>'
谢谢帮助!
I have a hard time testing my controller with before_filters, exceptions and some mocking and stubing.
Here is the controller:
before_filter :get_subject, :only => [:show, :edit, :update, :destroy, :update_field]
before_filter :user_has_to_belongs_to_subject_company, :only => [:show, :edit, :update, :destroy, :update_field]
def show
@messages = @subject.get_user_messages(current_user)
end
private
def get_subject
@subject = Subject.find(params[:id])
end
def user_has_to_belongs_to_subject_company
unless @current_user.company.eql?(@subject.company)
raise "Error: current_user does not belongs to subject's company"
end
end
And here is my spec file:
require 'spec_helper'
describe SubjectsController do
describe "for signed users" do
before(:each) do
@current_user = Factory(:user)
sign_in @current_user
end
describe "for user belonging to subject's company" do
before(:each) do
@subject = mock_model(Subject)
Subject.stub!(:find).with(@subject).and_return(@subject)
@current_user.stub_chain(:company, :eql?).and_return(true)
@subject.stub!(:company)
end
it "should not raise an exception" do
expect { get :show, :id => @subject }.to_not raise_error
end
end
describe "for user not belonging to subject's company" do
before(:each) do
@subject = mock_model(Subject)
Subject.stub!(:find).with(@subject).and_return(@subject)
@current_user.stub_chain(:company, :eql?).and_return(false)
@subject.stub!(:company)
end
it "should raise an exception" do
expect { get :show, :id => @subject }.to raise_error
end
end
end
end
And finally, here is the error message:
SubjectsController for signed users for user belonging to subject's company should not raise an exception
Failure/Error: expect { get :show, :id => @subject }.to_not raise_error
expected no Exception, got #<RuntimeError: Error: current_user does not belongs to subject's company>
# ./spec/controllers/subjects_controller_spec.rb:19:in `block (4 levels) in <top (required)>'
Thx for helping!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有看到问题,但这里有一个重构建议。如果您发现自己比平常使用更多的模拟和存根,也许是时候重新考虑您的接口了。在这种情况下,您可以使控制器更瘦,模型更胖。
I'm not seeing the problem, but here's a refactoring suggestion. If you find yourself using more mocks and stubs that usual, maybe it's time to reconsider your interfaces. In this case, you can make your controller skinnier and you model fatter.
如果您删除 @current_user 前面的 @
来获取
会发生什么并且在您的规范中,执行controller.stub!(:current_user).and_return @current_user
我认为问题是范围之一 - 您测试中的 @current_user 与@current_user 在你的控制器中。真正取决于“sign_in @current_user”的实现方式。
另外,也许您的 before_filter 可以将用户重定向到另一个页面并设置 flash[:error],而不是引发异常? before 过滤器是处理这种情况的正确位置,因此它不应该引发必须在其他地方救援的异常(或者如果没有,它会向用户显示 500 页)。
What happens if you delete the @ in front of @current_user in
to get
And in your specs, do controller.stub!(:current_user).and_return @current_user
I think the problem is one of scope - @current_user in your tests is different to @current_user in your controller. Really depends on how "sign_in @current_user" is implemented.
Also, instead of raising an exception, perhaps your before_filter could redirect the user to another page and set flash[:error]? The before filter is the right place to handle this situation, so it shouldn't raise an exception that would have to be rescued somewhere else (or if not, it would display a 500 page to the user).