使用 Rspec 和 Rspec 在 Rails 3 中测试会话水豚

发布于 2024-10-20 18:32:22 字数 1081 浏览 2 评论 0原文

我正在尝试使用 rspec、factory_girl & 编写集成测试。水豚。我还安装了黄瓜,但我没有使用它(据我所知)。

我基本上想用我的用户预填充数据库,然后转到我的主页并尝试登录。它应该重定向到 user_path(@user)。

但是,会话似乎没有在我的 /rspec/requests/ 集成测试中保留。

我的规范:/rspec/requests/users_spec.rb

require 'spec_helper'

describe "User flow" do

  before(:each) do
    @user = Factory(:user)
  end

  it "should login user" do

    visit("/index")

    fill_in :email, :with => @user.email
    fill_in :password, :with => @user.password
    click_button "Login"
    assert current_path == user_path(@user)
  end
end

返回:

Failures:

  1) User flow should login user
     Failure/Error: assert current_path == user_path(@user)
     <false> is not true.
     # (eval):2:in `send'
     # (eval):2:in `assert'
     # ./spec/requests/users_spec.rb:16

相反,它会重定向到我的 please_login_path - 如果由于任何原因登录失败(或者未设置 session[:user_id]),就会发生这种情况。

如果我尝试放置 session.inspect,它会作为 nil 对象失败。

如果我尝试在控制器测试(/rspec/controllers/sessions_spec.rb)中执行此操作,我可以毫无问题地访问会话,并且可以调用 session[:user_id]

I'm trying to write integration tests with rspec, factory_girl & capybara. I also have cucumber installed, but I'm not using it (to my knowledge).

I basically want to prepopulate the db with my user, then go to my home page and try to log in. It should redirect to user_path(@user).

However, sessions don't seem to be persisted in my /rspec/requests/ integration tests.

My spec: /rspec/requests/users_spec.rb

require 'spec_helper'

describe "User flow" do

  before(:each) do
    @user = Factory(:user)
  end

  it "should login user" do

    visit("/index")

    fill_in :email, :with => @user.email
    fill_in :password, :with => @user.password
    click_button "Login"
    assert current_path == user_path(@user)
  end
end

Returns:

Failures:

  1) User flow should login user
     Failure/Error: assert current_path == user_path(@user)
     <false> is not true.
     # (eval):2:in `send'
     # (eval):2:in `assert'
     # ./spec/requests/users_spec.rb:16

Instead, it redirects to my please_login_path - which should happen if the login fails for any reason (or if session[:user_id] is not set).

If I try to put session.inspect, it fails as a nil object.

If I try to do this in the controller tests (/rspec/controllers/sessions_spec.rb), I can access the session with no problem, and I can call session[:user_id]

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

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

发布评论

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

评论(3

云裳 2024-10-27 18:32:22

如果您使用 Devise,则需要包含 Warden::Test::Helpers (紧接在 spec_helper 的 require 之后是一个好地方),如下所示 典狱长维基

对会话的调用返回 nil,因为水豚在作为集成测试运行时不提供对它的访问。

If you are using Devise, you'll need to include Warden::Test::Helpers (right after the require of spec_helper is a good place) as outlined in the warden wiki.

The call to session is returning nil because capybara doesn't provide access to it when running as an integration test.

淡淡的优雅 2024-10-27 18:32:22

我也有同样的问题,虽然填写表格可能是某些人的选择,但我不得不推出自己的身份验证 ruby​​,因为我使用的是第三方身份验证系统(确切地说是 Janrain)....在我的测试中我结束了使用这样的东西:

这是我在spec/support/test_helpers_and_stuff.rb中的内容

module AuthTestHelper

  class SessionBackdoorController < ::ApplicationController
    def create
      sign_in User.find(params[:user_id])
      head :ok
    end
  end

  begin
    _routes = Rails.application.routes
    _routes.disable_clear_and_finalize = true
    _routes.clear!
    Rails.application.routes_reloader.paths.each{ |path| load(path) }
    _routes.draw do
      # here you can add any route you want
      match "/test_login_backdoor", to: "session_backdoor#create"
    end
    ActiveSupport.on_load(:action_controller) { _routes.finalize! }
  ensure
    _routes.disable_clear_and_finalize = false
  end

  def request_signin_as(user)
    visit "/test_login_backdoor?user_id=#{user.id}"
  end

  def signin_as(user)
    session[:session_user] = user.id
  end

end

然后在我的请求规范中,使用水豚和硒,我做了以下操作:

describe "Giveaway Promotion" do
  context "Story: A fan participates in a giveaway", js: :selenium do
    context "as a signed in user" do

      before :each do
        @user = Factory(:user)
        request_signin_as @user
      end

      it "should be able to participate as an already signed in user" do
        visit giveaway_path
        ....
      end
    end
  end
end

顺便说一句,在尝试了建议的解决方案后,我提出了解决方案< a href="https://stackoverflow.com/questions/5865555/how-to-do-integration-testing-with-rspec-and-devise-cancan">这篇文章和这篇文章,它们都不适合我。 (但他们确实启发了我的解决方案)

祝你好运!

I have the same problems and although filling out a form might be an option for some, I had to roll my own authentication ruby because I was using a third party auth system (Janrain to be exact).... in my tests I ended up using something like this:

Here is what I have in my spec/support/test_helpers_and_stuff.rb

module AuthTestHelper

  class SessionBackdoorController < ::ApplicationController
    def create
      sign_in User.find(params[:user_id])
      head :ok
    end
  end

  begin
    _routes = Rails.application.routes
    _routes.disable_clear_and_finalize = true
    _routes.clear!
    Rails.application.routes_reloader.paths.each{ |path| load(path) }
    _routes.draw do
      # here you can add any route you want
      match "/test_login_backdoor", to: "session_backdoor#create"
    end
    ActiveSupport.on_load(:action_controller) { _routes.finalize! }
  ensure
    _routes.disable_clear_and_finalize = false
  end

  def request_signin_as(user)
    visit "/test_login_backdoor?user_id=#{user.id}"
  end

  def signin_as(user)
    session[:session_user] = user.id
  end

end

Then in my request spec, with capybara and selenium, I did the following:

describe "Giveaway Promotion" do
  context "Story: A fan participates in a giveaway", js: :selenium do
    context "as a signed in user" do

      before :each do
        @user = Factory(:user)
        request_signin_as @user
      end

      it "should be able to participate as an already signed in user" do
        visit giveaway_path
        ....
      end
    end
  end
end

BTW, I came up with solutions after trying the proposed solutions to this post and this post and neither of them worked for me. (but they certainly inspired my solution)

Good luck!

紧拥背影 2024-10-27 18:32:22

您可能已经离开了这个话题,但我只是在同一个问题上苦苦挣扎。事实证明这是一个语法问题。我使用的是 :email:password 符号,我应该使用字符串来代替("email""password “)。

换句话说,尝试将其更改

fill_in :email, :with => @user.email
fill_in :password, :with => @user.password

为:

fill_in "email", :with => @user.email
fill_in "password", :with => @user.password

You've probably moved on from this, but I was just struggling with the same question. Turns out it was a matter of syntax. I was using symbols for :email and :password and I should've been using strings instead ("email" and "password").

In other words, try changing this:

fill_in :email, :with => @user.email
fill_in :password, :with => @user.password

to this:

fill_in "email", :with => @user.email
fill_in "password", :with => @user.password
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文