Rails,Restful身份验证和RSpec-如何测试需要身份验证的新模型
我使用Bort创建了一个学习应用程序,该应用程序是包括Restful Authentication和RSpec的基本应用程序。我已经启动并运行它,并添加了一个新对象,该对象要求用户必须先登录才能执行任何操作(控制器中的" before_filter:login_required")。 [编辑:我还应该提到新类的用户" has_many",只有该用户才能看到它。
我使用Rspec的生成器创建了新的模型/控制器,这些生成器创建了许多默认测试。如果没有before_filter
,它们全部通过,但是一旦before_filter
到位,就会有几次失败,这是可以预期的。
如何让生成的测试像有/没有登录用户一样运行?我是否需要一整批未登录的重定向测试?我认为这是一种模拟或者夹具技术,但是我对RSpec还是陌生的。良好的RSpec教程链接也将不胜感激。
解决方案
回答
我有一个非常相似的设置,下面是我目前用来测试这些东西的代码。在每个describe
中,我都输入:
it_should_behave_like "login-required object" def attempt_access; do_post; end
如果我们只需要登录,或者
it_should_behave_like "ownership-required object" def login_as_object_owner; login_as @product.user; end def attempt_access; do_put; end def successful_ownership_access response.should redirect_to(product_url(@product)) end
如果我们需要所有权。显然,每转一圈,辅助方法都会发生变化(很小),但这将为我们完成大部分工作。这是在我的spec_helper.rb中
shared_examples_for "login-required object" do it "should not be able to access this without logging in" do attempt_access response.should_not be_success respond_to do |format| format.html { redirect_to(login_url) } format.xml { response.status_code.should == 401 } end end end shared_examples_for "ownership-required object" do it_should_behave_like "login-required object" it "should not be able to access this without owning it" do attempt_access response.should_not be_success respond_to do |format| format.html { response.should be_redirect } format.xml { response.status_code.should == 401 } end end it "should be able to access this if you own it" do login_as_object_owner attempt_access if respond_to?(:successful_ownership_access) successful_ownership_access else response.should be_success end end end
回答
我找到了自己问题的一些答案。基本上,我需要了解如何从" restful_authentication"中模拟用户,以便即使我添加了" before_filter:login_required",也可以通过自动生成的rspec控制器测试。
这是我刚刚找到的一些资源:
RSpec:应该像
rspec,restful_authentication和login_required
在控制器规格中使用restful_authentication current_user
使CRUD控制器RSpec干燥
回答
为了模拟正在登录的用户,我侵入控制器以手动设置@ current_user
:
module AuthHelper protected def login_as(model, id_or_attributes = {}) attributes = id_or_attributes.is_a?(Fixnum) ? {:id => id} : id_or_attributes @current_user = stub_model(model, attributes) target = controller rescue template target.instance_variable_set '@current_user', @current_user if block_given? yield target.instance_variable_set '@current_user', nil end return @current_user end def login_as_user(id_or_attributes = {}, &block) login_as(User, id_or_attributes, &block) end end
回答
当不测试身份验证,而是测试需要验证用户身份的控制器时,我通常会添加过滤方法:
before(:each) do controller.stub!(:authenticate).and_return(true) end
上面的示例适用于将我的before_filter设置为authenticate方法的情况:
before_filter :authenticate
我的应用中的身份验证使用HTTP基本身份验证,但实际上可以是任何其他身份验证机制。
private def authenticate authenticate_or_request_with_http_basic do |user,password| user == USER_NAME && password == PASSWORD end end
我认为这是一种非常简单的测试方法。