Rails、Restful 身份验证和 RSpec - 如何测试需要身份验证的新模型

发布于 2024-07-04 21:21:41 字数 576 浏览 5 评论 0原文

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

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

如何让生成的测试像有/没有登录用户一样运行? 我是否需要一整批未登录的匹配 - 重定向测试? 我认为这是某种模拟或固定技术,但我对 RSpec 很陌生并且有点迷失。 好的 RSpec 教程链接也将受到赞赏。

I've created a learning application using Bort, which is a base app that includes Restful Authentication and RSpec. I've got it up and running and added a new object that requires users to be logged in before they can do anything(before_filter :login_required in the controller). [edit: I should also mention that the user has_many of the new class and only the user should be able to see it.]

I've created the new model/controller using Rspec's generators which have created a number of default tests. They all pass if there is no before_filter but several fail, as should be expected, once the before_filter is in place.

How do I get the generated tests to run as if there is/is not a logged in user? Do I need a whole batch of matching not logged in - redirect tests? I assume it is some sort of mocking or fixture technique but I am new to RSpec and a bit adrift. Good RSpec tutorial links would also be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

家住魔仙堡 2024-07-11 21:21:41

为了模拟正在登录的用户,我侵入控制器以手动设置 @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

To mock a user being logged in, I hack into the controller to set @current_user manually:

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
冰之心 2024-07-11 21:21:41

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

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

RSpec:它应该表现得像

rspec 、restful_authentication 和 login_required

在控制器规范内使用restful_authentication current_user< /a>

干燥您的 CRUD 控制器 RSpecs

I found a few answers to my own question. Basically, I needed to understand how to mock out the user from restful_authentication so that the autogenerated rspec controller tests could pass even though I had added before_filter: login_required.

Here are a few of my just found resources:

RSpec: It Should Behave Like

rspec, restful_authentication, and login_required

using restful_authentication current_user inside controller specs

DRYing up your CRUD controller RSpecs

青朷 2024-07-11 21:21:41

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

before(:each) do
  controller.stub!(:authenticate).and_return(true)
end

上面的示例在我的 before_filter 设置为身份验证方法的情况下工作:

before_filter :authenticate

并且我的应用程序中的身份验证使用 HTTP 基本身份验证,但它实际上可以是任何其他身份验证机制。

private
def authenticate
  authenticate_or_request_with_http_basic do |user,password|
    user == USER_NAME && password == PASSWORD
  end
end

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

When not testing the authentication but testing the controllers that needs the user to be authenticated I usually stub the filter method:

before(:each) do
  controller.stub!(:authenticate).and_return(true)
end

The above example works where my before_filter is set to the authenticate method:

before_filter :authenticate

and the authenticate in my app uses HTTP Basic Authentication, but it really can be any other authentication mechanism.

private
def authenticate
  authenticate_or_request_with_http_basic do |user,password|
    user == USER_NAME && password == PASSWORD
  end
end

I think it's a pretty straightforward way to test.

流星番茄 2024-07-11 21:21:41

我有一个非常相似的设置,下面是我当前用来测试这个东西的代码。 在我输入的每个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

I have a very similar setup, and below is the code I'm currently using to test this stuff. In each of the describes I put in:

it_should_behave_like "login-required object"
def attempt_access; do_post; end

If all you need is a login, or

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

If you need ownership. Obviously, the helper methods change (very little) with each turn, but this does most of the work for you. This is in my 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文