ruby-on-rails - 如何使用 RSpec 模拟登录?

标签 ruby-on-rails rspec factory-bot

我已经使用 Rails 几年了,并且已经制作了一些正在生产中的还过得去的应用程序。我一直避免进行任何测试,但我决定纠正这一点。我正在尝试为我为已经启动并运行但正在不断修改的工作编写的应用程序编写一些测试。我担心任何更改都会破坏一切,所以我想启动并运行一些测试。我读过 RSpec 书,观看了一些截屏视频,但很难开始(在我看来,只有真正完成后才能理解)。

我正在尝试编写对我的 ReportsController 进行简单测试的内容。我的应用程序的问题在于,几乎整个事情都位于身份验证层后面。如果你没有登录,什么都不起作用,所以我必须先模拟登录,然后才能发送一个简单的获取请求(尽管我想我应该编写一些测试以确保没有登录就什么都不起作用 - 我会去稍后)。

我已经用 RSpec、Capybara、FactoryGirl 和 Guard 设置了一个测试环境(不确定使用哪些工具,所以使用了 Railscasts 的建议)。到目前为止,我编写测试的方法是在 FactoryGirl 中创建一个用户,如下所示;

FactoryGirl.define do
  sequence(:email) {|n| "user#{n}@example.com"}
  sequence(:login) {|n| "user#{n}"}
  factory :user do
    email {FactoryGirl.generate :email}
    login {FactoryGirl.generate :login}
    password "abc"
    admin false
    first_name "Bob"
    last_name "Bobson"
  end
end

然后像这样编写我的测试;

require 'spec_helper'

describe ReportsController do
  describe "GET 'index'" do
    it "should be successful" do
      user = Factory(:user)
      visit login_path
      fill_in "login", :with => user.login
      fill_in "password", :with => user.password
      click_button "Log in"
      get 'index'
      response.should be_success
    end
  end
end

这失败了;

  1) ReportsController GET 'index' should be successful
     Failure/Error: response.should be_success
       expected success? to return true, got false
     # ./spec/controllers/reports_controller_spec.rb:13:in `block (3 levels) in <top (required)>'

有趣的是,如果我将测试更改为 response.should be_redirect,测试就会通过,这表明在那之前一切正常,但登录未被识别。

所以我的问题是我必须做什么才能使此登录正常工作。我是否需要在数据库中创建与 FactoryGirl 凭据匹配的用户?如果是这样,FactoryGirl 在这里有什么意义(我什至应该使用它)?我如何在测试环境中创建这个假用户?我的身份验证系统是一个非常简单的自制系统(基于 Railscasts episode 250 )。这种登录行为可能必须在我的几乎所有测试中复制,那么我该如何在我的代码中执行一次并使其适用于所有地方?

我意识到这是一个很大的问题,所以我感谢您的浏览。

最佳答案

答案取决于您的身份验证实现。通常,当用户登录时,您将设置一个 session 变量来记住该用户,例如 session[:user_id]。您的 Controller 将在 before_filter 中检查登录情况,如果不存在此类 session 变量,则进行重定向。我假设您已经在做类似的事情了。

要在测试中使其正常工作,您必须手动将用户信息插入到 session 中。以下是我们在工作中使用的部分内容:

# spec/support/spec_test_helper.rb
module SpecTestHelper   
  def login_admin
    login(:admin)
  end

  def login(user)
    user = User.where(:login => user.to_s).first if user.is_a?(Symbol)
    request.session[:user] = user.id
  end

  def current_user
    User.find(request.session[:user])
  end
end

# spec/spec_helper.rb
RSpec.configure do |config|
  config.include SpecTestHelper, :type => :controller
end

现在,在我们的任何 Controller 示例中,我们都可以调用 login(some_user) 来模拟以该用户身份登录。

<小时/>

我还应该提到,您似乎正在此 Controller 测试中进行集成测试。通常,您的 Controller 测试应该仅模拟对单个 Controller 操作的请求,例如:

it 'should be successful' do
  get :index
  response.should be_success
end

这专门测试单个 Controller 操作,这是您在一组 Controller 测试中想要的。然后您可以使用 Capybara/Cucumber 进行表单、 View 和 Controller 的端到端集成测试。

关于ruby-on-rails - 如何使用 RSpec 模拟登录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10121835/

相关文章:

javascript - Rails 中的远程模态形式,不触发 AJAX 事件

ruby-on-rails - 之前的 Rspec(:each) works but before(:all) does not

ruby - 如何在 rspec 中 stub rand?

ruby-on-rails - 未调用 RSpec Controller 测试失败方法

ruby-on-rails - 使用 FactoryGirl 别名属性的正确方法是什么?

ruby-on-rails - Factory Girl + Mongoid 在装置中嵌入文档

ruby-on-rails - 无法运行 Rails 服务器

javascript - 使用中间人的页面特定 JavaScript

ruby - 新生成的 Guardfile 为空

ruby - 即使提供了记录,FactoryBot 也会创建记录