17

我使用Bort创建了一个学习应用程序,它是一个包含 Restful Authentication 和 RSpec 的基础应用程序。我已经启动并运行它并添加了一个新对象,该对象需要用户登录才能执行任何操作(before_filter :login_required在控制器中)。[编辑:我还应该提到has_many新类的用户并且只有用户应该能够看到它。]

我使用 Rspec 的生成器创建了新的模型/控制器,这些生成器创建了许多默认测试。如果没有before_filter但有几个失败,它们都会通过,正如预期的那样,一旦before_filter到位。

如何让生成的测试像有/没有登录用户一样运行?我是否需要一整批未登录的匹配 - 重定向测试?我认为这是某种模拟或固定技术,但我是 RSpec 的新手,有点飘忽不定。好的 RSpec 教程链接也将不胜感激。

4

4 回答 4

7

我有一个非常相似的设置,下面是我目前用来测试这些东西的代码。在我输入的每个describes 中:

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
于 2008-09-15T19:04:35.737 回答
7

当不测试身份验证但测试需要用户进行身份验证的控制器时,我通常存根过滤器方法:

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

我认为这是一种非常简单的测试方法。

于 2009-12-22T01:02:51.473 回答
4

我为自己的问题找到了一些答案。基本上,我需要了解如何模拟用户,restful_authentication以便自动生成的 rspec 控制器测试可以通过,即使我添加了before_filter: login_required.

以下是我刚刚找到的一些资源:

RSpec:它应该表现得像

rspec、restful_authentication 和 login_required

在控制器规范中使用 restful_authentication current_user

干燥你的 CRUD 控制器 RSpecs

于 2008-09-16T12:16:55.430 回答
1

为了模拟正在登录的用户,我侵入控制器@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
于 2008-09-27T16:44:21.557 回答