如何使用 RSpec 模拟登录? [英] How do I simulate a login with RSpec?

查看:18
本文介绍了如何使用 RSpec 模拟登录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Rails 已经有几年了,并且已经开发了几个可以通过的应用程序.不过,我一直避免进行任何测试,因此我决定纠正它.我正在尝试为我为已经启动并正在运行但正在不断修订的工作编写的应用程序编写一些测试.我担心任何更改都会破坏事情,所以我想启动并运行一些测试.我读过 RSpec 的书,看过一些截屏视频,但我很难开始(这让我印象深刻,因为你只有在实际完成后才能理解).

I have been playing with Rails for a couple of years now and have produced a couple of passable apps that are in production. I've always avoided doing any testing though and I have decided to rectify that. I'm trying to write some tests for an app that I wrote for work that is already up and running but undergoing constant revision. I'm concerned that any changes will break things so I want to get some tests up and running. I've read the RSpec book, watched a few screencasts but am struggling to get started (it strikes me as the sort of thing you only understand once you've actually done it).

我正在尝试编写一个简单的 ReportsController 测试.我的应用程序的问题是几乎整个事情都位于身份验证层之后.如果你没有登录,什么都不起作用,所以我必须在我什至发送一个简单的 get 请求之前模拟登录(虽然我想我应该写一些测试来确保没有登录就没有任何工作 - 我会得到以后再说).

I'm trying to write what should be a simple test of my ReportsController. The problem with my app is that pretty much the entire thing sits behind an authentication layer. Nothing works if you're not logged in so I have to simulate a login before I can even send forth a simple get request (although I guess I should write some tests to make sure that nothing works without a login - I'll get to that later).

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

I've set up a testing environment with RSpec, Capybara, FactoryGirl and Guard (wasn't sure which tools to use so used Railscasts' suggestions). The way I've gone about writing my test so far is to create a user in FactoryGirl like so;

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

然后像这样写我的测试;

and then write my test like so;

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,则测试通过,这表明在此之前一切正常,但无法识别登录.

Interestingly if I change my test to response.should be_redirect, the test passes which suggests to me that everything is working up until that point but the login is not being recognised.

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

So my question is what do I have to do to make this login work. Do I need to create a user in the database that matches the FactoryGirl credentials? If so, what is the point of FactoryGirl here (and should I even be using it)? How do I go about creating this fake user in the testing environment? My authentication system is a very simple self-made one (based on Railscasts episode 250). This logging in behaviour will presumably have to replicated for almost all of my tests so how do I go about doing it once in my code and having it apply everywhere?

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

I realise this is a big question so I thank you for having a look.

推荐答案

答案取决于您的身份验证实施.通常,当用户登录时,您将设置一个会话变量来记住该用户,例如 session[:user_id].您的控制器将检查 before_filter 中的登录信息,如果不存在此类会话变量,则重定向.我想你已经在做这样的事情了.

The answer depends on your authentication implementation. Normally, when a user logs in, you'll set a session variable to remember that user, something like session[:user_id]. Your controllers will check for a login in a before_filter and redirect if no such session variable exists. I assume you're already doing something like this.

要在您的测试中使用此功能,您必须手动将用户信息插入会话中.以下是我们在工作中使用的部分内容:

To get this working in your tests, you have to manually insert the user information into the session. Here's part of what we use at work:

# 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

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

Now in any of our controller examples, we can call login(some_user) to simulate logging in as that user.

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

I should also mention that it looks like you're doing integration testing in this controller test. As a rule, your controller tests should only be simulating requests to individual controller actions, like:

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

这专门测试单个控制器操作,这是您在一组控制器测试中想要的.然后您可以使用 Capybara/Cucumber 对表单、视图和控制器进行端到端的集成测试.

This specifically tests a single controller action, which is what you want in a set of controller tests. Then you can use Capybara/Cucumber for end-to-end integration testing of forms, views, and controllers.

这篇关于如何使用 RSpec 模拟登录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆