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

查看:72
本文介绍了如何使用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在这里有什么意义(我什至应该使用它)?如何在测试环境中创建这个假用户?我的身份验证系统是一个非常简单的自制系统(基于铁路广播第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天全站免登陆